Commit 3491ea02 authored by MagoKimbra's avatar MagoKimbra

Update V4.2.84

Add Mesh Bed Level
parent dd3c8447
......@@ -127,6 +127,8 @@
* M407 - Displays measured filament diameter
* M408 - Report JSON-style response
* 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
* M500 - stores paramters in EEPROM
* 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
* Add Cooler and Hot Chamber
* Add Laser Beam PWM and raster base64
......
......@@ -8,6 +8,7 @@
* - Endstop pullup resistors
* - Endstops logic
* - Endstops min or max
* - Min Z height for homing
* - Stepper enable logic
* - Stepper step logic
* - Stepper direction
......@@ -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 **********************************
*****************************************************************************************
......@@ -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 *
......@@ -292,9 +325,6 @@
#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_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_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.
......@@ -467,4 +497,4 @@
#define DEFAULT_ZWOBBLE 0, 0, 0 // A, W, P
/*****************************************************************************************/
#endif
\ No newline at end of file
#endif
......@@ -9,6 +9,7 @@
* - Endstop pullup resistors
* - Endstops logic
* - Endstops min or max
* - Min Z height for homing
* - Stepper enable logic
* - Stepper step logic
* - Stepper direction
......@@ -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 **********************************
*****************************************************************************************
......@@ -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 *
......@@ -293,9 +326,9 @@
#define ABL_PROBE_PT_1_X 15
#define ABL_PROBE_PT_1_Y 180
#define ABL_PROBE_PT_2_X 15
#define ABL_PROBE_PT_2_Y 20
#define ABL_PROBE_PT_3_X 170
#define ABL_PROBE_PT_3_Y 20
#define ABL_PROBE_PT_2_Y 15
#define ABL_PROBE_PT_3_X 180
#define ABL_PROBE_PT_3_Y 15
// no AUTO_BED_LEVELING_GRID
// Offsets to the probe relative to the extruder tip (Hotend - Probe)
......@@ -314,9 +347,6 @@
#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_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_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.
......@@ -324,8 +354,8 @@
//#define Z_PROBE_END_SCRIPT "G1 Z10 F8000\nG1 X10 Y10\nG1 Z0.5" // These commands will be executed in the end of G29 routine.
// 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 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 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.
/*****************************************************************************************/
......@@ -336,26 +366,26 @@
* If you have enabled the Auto bed levelling this add the Support for *
* 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 *
* 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. *
* *
* 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. *
* *
* WARNING: The Z MIN endstop will need to set properly as it would *
* without a Z PROBE to prevent head crashes and premature stopping *
* 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. *
* 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. *
* *
* WARNING: Setting the wrong pin may have unexpected and potentially *
* 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
......@@ -364,10 +394,10 @@
/*****************************************************************************************
******************************** Manual home positions **********************************
/*****************************************************************************************/
*****************************************************************************************/
// The position of the homing switches
//#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 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)
//Manual homing switch locations:
#define MANUAL_X_HOME_POS 0
......
......@@ -23,6 +23,7 @@
* - Software endstops
* - Endstops only for homing
* - Abort on endstop hit feature
* - Mesh Level Area
* - R/C Servo
* - Late Z axis
* - Ahead slowdown
......@@ -437,6 +438,23 @@
**************************************************************************/
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
#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))
/**************************************************************************/
/**************************************************************************
......
......@@ -179,6 +179,14 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR(i, home_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)
EEPROM_WRITE_VAR(i, zprobe_zoffset);
#endif
......@@ -338,6 +346,12 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, home_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)
EEPROM_READ_VAR(i, zprobe_zoffset);
#endif
......@@ -540,6 +554,10 @@ void Config_ResetDefault() {
max_z_jerk = DEFAULT_ZJERK;
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)
zprobe_zoffset = Z_PROBE_OFFSET_FROM_EXTRUDER;
#elif !MECH(DELTA)
......@@ -745,6 +763,23 @@ void Config_ResetDefault() {
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 (!forReplay) {
ECHO_LM(CFG, "AD595 Offset and Gain:");
......
......@@ -24,7 +24,7 @@
#define CONFIGURATION_VERSION_H
#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 STRING_DISTRIBUTION_DATE __DATE__ " " __TIME__ // build date and time
// It might also be appropriate to define a location where additional information can be found
......
......@@ -170,6 +170,8 @@
* M407 - Display measured filament diameter
* M408 - Report JSON-style response
* 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
* M500 - Store parameters in EEPROM
* M501 - Read parameters from EEPROM (if you need reset them after you changed them temporarily).
......
......@@ -52,6 +52,10 @@
#include "module/HAL/HAL.h"
#include "module/communication/communication.h"
#if ENABLED(MESH_BED_LEVELING)
#include "module/mbl/mesh_bed_leveling.h"
#endif
#include "Configuration_Store.h"
#include "module/language/language.h"
......
......@@ -12,11 +12,11 @@
*
* 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
* 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/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
......
......@@ -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) {
if (DEBUGGING(INFO)) {
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", current_position);
}
......@@ -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();
//uncorrected_position.debug("position before");
vector_3 corrected_position = plan_get_position();
vector_3 corrected_position = plan_adjusted_position();
//corrected_position.debug("position after");
current_position[X_AXIS] = corrected_position.x;
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
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[Y_AXIS] = corrected_position.y;
current_position[Z_AXIS] = corrected_position.z;
......@@ -3008,7 +3008,7 @@ inline void wait_heater(bool no_wait_for_cooling = true) {
now = millis();
if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting
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();
#endif
#if TEMP_RESIDENCY_TIME > 0
......@@ -3083,9 +3083,7 @@ inline void wait_bed(bool no_wait_for_cooling = true) {
now = millis();
if (ELAPSED(now, next_temp_ms)) { //Print Temp Reading every 1 second while heating up.
next_temp_ms = now + 1000UL;
#if HAS(TEMP_0) || HAS(TEMP_BED) || ENABLED(HEATER_0_USES_MAX6675)
print_heaterstates();
#endif
print_heaterstates();
#if TEMP_BED_RESIDENCY_TIME > 0
ECHO_M(SERIAL_W);
if (residency_start_ms) {
......@@ -3297,26 +3295,12 @@ void gcode_get_destination() {
if(code_seen(axis_codes[E_AXIS])) IDLE_OOZING_retract(false);
#endif
#if HOTENDS == 1
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] : 0);
else
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];
for (int i = X_AXIS; i <= E_AXIS; i++) {
if (code_seen(axis_codes[i]))
destination[i] = code_value() + (axis_relative_modes[i] || relative_mode ? current_position[i] : 0);
else
destination[i] = current_position[i];
}
if (code_seen('F')) {
float next_feedrate = code_value();
......@@ -3676,6 +3660,10 @@ inline void gcode_G28() {
// Wait for planner moves to finish!
st_synchronize();
#if EXTRUDERS > 1
active_extruder = active_driver = 0;
#endif
// For auto bed leveling, clear the level matrix
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
plan_bed_level_matrix.set_to_identity();
......@@ -3683,6 +3671,15 @@ inline void gcode_G28() {
reset_bed_level();
#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();
/**
......@@ -3731,29 +3728,37 @@ inline void gcode_G28() {
#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);
if (DEBUGGING(INFO))
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
destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed
// Raise Z before homing any other axes and z is not already high enough (never lower z)
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)) {
ECHO_LMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
DEBUG_POS(" > (home_all_axis || homeZ)", destination);
ECHO_EMV("Raise Z (before homing) to ", (MIN_Z_HEIGHT_FOR_HOMING));
DEBUG_POS("> (home_all_axis || homeZ)", current_position);
DEBUG_POS("> (home_all_axis || homeZ)", destination);
}
feedrate = max_feedrate[Z_AXIS] * 60;
line_to_destination();
st_synchronize();
#endif
} // home_all_axis || homeZ
/**
* 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
#if ENABLED(QUICK_HOME)
......@@ -3849,215 +3854,130 @@ inline void gcode_G28() {
// Home Z last if homing towards the bed
#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();
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
if (home_all_axis || homeZ) {
feedrate = saved_feedrate;
feedrate_multiplier = saved_feedrate_multiplier;
refresh_cmd_timeout();
endstops.hit_on_purpose(); // clear endstop hit flags
sync_plan_position();
#if ENABLED(Z_SAFE_HOMING) && ENABLED(AUTO_BED_LEVELING_FEATURE)// Z Safe mode activated.
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>");
// 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();
}
if (home_all_axis) {
// 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();
}
/**
* 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();
// 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();
}
/**
* Set the Z probe (or just the nozzle) destination to the safe
* homing point
*/
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[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed
feedrate = xy_travel_speed;
// 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();
if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", current_position);
DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", destination);
}
// FINISH MANUAL BED LEVEL
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 >>>");
// Move in the XY plane
line_to_destination();
st_synchronize();
if (home_all_axis) {
/**
* Update the current positions for XY
*/
current_position[X_AXIS] = destination[X_AXIS];
current_position[Y_AXIS] = destination[Y_AXIS];
current_position[Z_AXIS] = 0;
sync_plan_position();
// Home the Z axis
HOMEAXIS(Z);
}
else if (homeZ) { // Don't need to Home Z twice
// Let's see if X and Y are homed
if (axis_homed[X_AXIS] && axis_homed[Y_AXIS]) {
/**
* 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];
if ( cpx >= X_MIN_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_MAX_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)) {
// Home the Z axis
HOMEAXIS(Z);
}
else {
LCD_MESSAGEPGM(MSG_ZPROBE_OUT);
ECHO_LM(DB, MSG_ZPROBE_OUT);
}
}
else {
axis_unhomed_error();
}
} // !home_all_axes && homeZ
//
// Set the 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[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
feedrate = xy_travel_speed;
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
DEBUG_POS(" > home_all_axis", current_position);
DEBUG_POS(" > home_all_axis", destination);
}
#elif ENABLED(Z_SAFE_HOMING)
// This could potentially move X, Y, Z all together
line_to_destination();
st_synchronize();
if (home_all_axis || homeZ) {
// Set current X, Y is the Z_SAFE_HOMING_POINT minus PROBE_OFFSET_FROM_EXTRUDER
current_position[X_AXIS] = destination[X_AXIS];
current_position[Y_AXIS] = destination[Y_AXIS];
if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>");
HOMEAXIS(Z);
}
else if (homeZ) { // Don't need to Home Z twice
// Let's see if X and Y are homed
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!
float cpx = current_position[X_AXIS], cpy = current_position[Y_AXIS];
if ( cpx >= X_MIN_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_MAX_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)) {
// Set the plan current position to X, Y, 0
// Let's see if X and Y are homed
if (axis_homed[X_AXIS] && axis_homed[Y_AXIS]) {
current_position[Z_AXIS] = 0;
plan_set_position(cpx, cpy, 0, current_position[E_AXIS]);
sync_plan_position();
// 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;
destination[X_AXIS] = round(Z_SAFE_HOMING_X_POINT);
destination[Y_AXIS] = round(Z_SAFE_HOMING_Y_POINT);
destination[Z_AXIS] = current_position[Z_AXIS] = 0;
feedrate = xy_travel_speed;
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);
DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", current_position);
DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", destination);
}
// This could potentially move X, Y, Z all together
line_to_destination();
st_synchronize();
// Home the Z axis
// Set current X, Y is the Z_SAFE_HOMING_POINT minus PROBE_OFFSET_FROM_EXTRUDER
current_position[X_AXIS] = destination[X_AXIS];
current_position[Y_AXIS] = destination[Y_AXIS];
HOMEAXIS(Z);
}
else {
LCD_MESSAGEPGM(MSG_ZPROBE_OUT);
ECHO_LM(DB, MSG_ZPROBE_OUT);
LCD_MESSAGEPGM(MSG_POSITION_UNKNOWN);
ECHO_LM(ER, MSG_POSITION_UNKNOWN);
}
}
else {
axis_unhomed_error();
}
}
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#elif ENABLED(Z_SAFE_HOMING)
if (home_all_axis || homeZ) {
if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>");
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
// Let's see if X and Y are homed
if (axis_homed[X_AXIS] && axis_homed[Y_AXIS]) {
current_position[Z_AXIS] = 0;
sync_plan_position();
#else // !Z_SAFE_HOMING
destination[X_AXIS] = round(Z_SAFE_HOMING_X_POINT);
destination[Y_AXIS] = round(Z_SAFE_HOMING_Y_POINT);
destination[Z_AXIS] = current_position[Z_AXIS] = 0;
feedrate = xy_travel_speed;
HOMEAXIS(Z);
if (DEBUGGING(INFO)) {
DEBUG_POS(" > home_all_axis", current_position);
DEBUG_POS(" > home_all_axis", destination);
}
#endif // !Z_SAFE_HOMING
if (DEBUGGING(INFO)) DEBUG_POS("> (home_all_axis || homeZ) > final", current_position);
// This could potentially move X, Y, Z all together
line_to_destination();
st_synchronize();
}
// Set current X, Y is the Z_SAFE_HOMING_POINT minus PROBE_OFFSET_FROM_EXTRUDER
current_position[X_AXIS] = destination[X_AXIS];
current_position[Y_AXIS] = destination[Y_AXIS];
HOMEAXIS(Z);
}
else {
LCD_MESSAGEPGM(MSG_POSITION_UNKNOWN);
ECHO_LM(ER, MSG_POSITION_UNKNOWN);
}
}
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#endif // Z_SAFE_HOMING
#endif // Z_HOME_DIR < 0
sync_plan_position();
......@@ -4068,7 +3988,30 @@ inline void gcode_G28() {
sync_plan_position_delta();
#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 MECH(DELTA)
......@@ -4106,11 +4049,189 @@ inline void gcode_G28() {
#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");
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) {
ECHO_M("?Probe ");
......@@ -4237,7 +4358,7 @@ inline void gcode_G28() {
// vector_3 corrected_position = plan_get_position_mm();
// 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");
current_position[X_AXIS] = uncorrected_position.x;
current_position[Y_AXIS] = uncorrected_position.y;
......@@ -4442,7 +4563,7 @@ inline void gcode_G28() {
float x_tmp = current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER,
y_tmp = current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER,
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)) {
ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > z_tmp = ", z_tmp);
......@@ -4867,7 +4988,9 @@ inline void gcode_G92() {
current_position[i] = v;
if (i == E_AXIS) {
plan_set_e_position(v);
#if DISABLED(MUVE_Z_PEEL)
plan_set_e_position(v);
#endif
}
else {
position_shift[i] += v - p; // Offset the coordinate space
......@@ -7295,6 +7418,47 @@ inline void gcode_M400() { st_synchronize(); }
*/
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
* current_position and the nearest "reference point."
......@@ -7960,6 +8124,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
{
// Save current position to return to after applying extruder offset
set_destination_to_current();
#if ENABLED(DUAL_X_CARRIAGE)
if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning() &&
(delayed_move_time != 0 || current_position[X_AXIS] != x_home_pos(active_extruder))) {
......@@ -7984,10 +8149,12 @@ inline void gcode_T(uint8_t tmp_extruder) {
}
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
if (active_extruder == 0 || active_extruder_parked)
current_position[X_AXIS] = inactive_extruder_x_pos;
else
current_position[X_AXIS] = destination[X_AXIS] + duplicate_hotend_x_offset;
inactive_extruder_x_pos = destination[X_AXIS];
extruder_duplication_enabled = false;
}
......@@ -7998,14 +8165,12 @@ inline void gcode_T(uint8_t tmp_extruder) {
active_extruder_parked = true;
delayed_move_time = 0;
}
#else // !DUAL_X_CARRIAGE
#if ENABLED(MKR4)
#if (EXTRUDERS == 4) && HAS(E0E2) && HAS(E1E3) && (DRIVER_EXTRUDERS == 2)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder)
{
#elif ENABLED(MKR4)
#if (EXTRUDERS == 4) && HAS(E0E2) && HAS(E1E3) && (DRIVER_EXTRUDERS == 2)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder) {
case 0:
WRITE_RELE(E0E2_CHOICE_PIN, LOW);
WRITE_RELE(E1E3_CHOICE_PIN, LOW);
......@@ -8034,12 +8199,11 @@ inline void gcode_T(uint8_t tmp_extruder) {
delay_ms(500); // 500 microseconds delay for relay
enable_e3();
break;
}
#elif (EXTRUDERS == 4) && HAS(E0E1) && HAS(E0E2) && HAS(E0E3) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder)
{
}
#elif (EXTRUDERS == 4) && HAS(E0E1) && HAS(E0E2) && HAS(E0E3) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder) {
case 0:
WRITE_RELE(E0E1_CHOICE_PIN, LOW);
WRITE_RELE(E0E2_CHOICE_PIN, LOW);
......@@ -8072,12 +8236,11 @@ inline void gcode_T(uint8_t tmp_extruder) {
delay_ms(500); // 500 microseconds delay for relay
enable_e0();
break;
}
#elif (EXTRUDERS == 3) && HAS(E0E2) && (DRIVER_EXTRUDERS == 2)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder)
{
}
#elif (EXTRUDERS == 3) && HAS(E0E2) && (DRIVER_EXTRUDERS == 2)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder) {
case 0:
WRITE_RELE(E0E2_CHOICE_PIN, LOW);
active_driver = 0;
......@@ -8096,12 +8259,11 @@ inline void gcode_T(uint8_t tmp_extruder) {
delay_ms(500); // 500 microseconds delay for relay
enable_e0();
break;
}
#elif (EXTRUDERS == 3) && HAS(E0E1) && HAS(E0E2) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder)
{
}
#elif (EXTRUDERS == 3) && HAS(E0E1) && HAS(E0E2) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder) {
case 0:
WRITE_RELE(E0E1_CHOICE_PIN, LOW);
WRITE_RELE(E0E2_CHOICE_PIN, LOW);
......@@ -8123,12 +8285,11 @@ inline void gcode_T(uint8_t tmp_extruder) {
delay_ms(500); // 500 microseconds delay for relay
enable_e0();
break;
}
#elif (EXTRUDERS == 2) && HAS(E0E1) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder)
{
}
#elif (EXTRUDERS == 2) && HAS(E0E1) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement
disable_e();
switch(target_extruder) {
case 0:
WRITE_RELE(E0E1_CHOICE_PIN, LOW);
active_driver = 0;
......@@ -8141,64 +8302,113 @@ inline void gcode_T(uint8_t tmp_extruder) {
delay_ms(500); // 500 microseconds delay for relay
enable_e0();
break;
}
#endif // E0E1_CHOICE_PIN E0E2_CHOICE_PIN E1E3_CHOICE_PIN
previous_extruder = active_extruder;
active_extruder = target_extruder;
ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver);
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#elif ENABLED(NPR2)
long csteps;
st_synchronize(); // Finish all movement
if (old_color == 99) {
csteps = (color_position[target_extruder]) * color_step_moltiplicator;
}
else {
csteps = (color_position[target_extruder] - color_position[old_color]) * color_step_moltiplicator;
}
if (csteps < 0) colorstep(-csteps, false);
if (csteps > 0) colorstep(csteps, true);
previous_extruder = active_extruder;
old_color = active_extruder = target_extruder;
active_driver = 0;
ECHO_LMV(DB, SERIAL_ACTIVE_COLOR, (int)active_extruder);
#elif HAS(DONDOLO)
st_synchronize();
servo[DONDOLO_SERVO_INDEX].attach(0);
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)
delay_ms(DONDOLO_SERVO_DELAY);
servo[DONDOLO_SERVO_INDEX].detach();
#endif // E0E1_CHOICE_PIN E0E2_CHOICE_PIN E1E3_CHOICE_PIN
previous_extruder = active_extruder;
active_extruder = target_extruder;
ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver);
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#elif ENABLED(NPR2)
long csteps;
st_synchronize(); // Finish all movement
if (old_color == 99)
csteps = (color_position[target_extruder]) * color_step_moltiplicator;
else
csteps = (color_position[target_extruder] - color_position[old_color]) * color_step_moltiplicator;
if (csteps < 0) colorstep(-csteps, false);
if (csteps > 0) colorstep(csteps, true);
previous_extruder = active_extruder;
old_color = active_extruder = target_extruder;
active_driver = 0;
ECHO_LMV(DB, SERIAL_ACTIVE_COLOR, (int)active_extruder);
#elif HAS(DONDOLO)
float diff;
st_synchronize();
servo[DONDOLO_SERVO_INDEX].attach(0);
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);
}
// Raise Z before switch servo
if (diff < 0) {
#if MECH(DELTA)
sync_plan_position_delta();
#else
sync_plan_position();
#endif
previous_extruder = active_extruder;
#if ENABLED(DONDOLO_SINGLE_MOTOR)
active_extruder = target_extruder;
active_driver = 0;
#elif ENABLED(DONDOLO_DUAL_MOTOR)
active_driver = active_extruder = target_extruder;
// 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)
delay_ms(DONDOLO_SERVO_DELAY);
servo[DONDOLO_SERVO_INDEX].detach();
#endif
if (diff >= 0) {
#if MECH(DELTA)
sync_plan_position_delta();
#else
sync_plan_position();
#endif
set_stepper_direction(true);
ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver);
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#else
previous_extruder = active_extruder;
// Move to the "old position" (move the extruder into place)
if (IsRunning()) prepare_move();
}
previous_extruder = active_extruder;
#if ENABLED(DONDOLO_SINGLE_MOTOR)
active_extruder = target_extruder;
active_driver = 0;
#elif ENABLED(DONDOLO_DUAL_MOTOR)
active_driver = active_extruder = target_extruder;
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#endif // end MKR4 || NPR2 || DONDOLO
#endif // end no DUAL_X_CARRIAGE
#endif
set_stepper_direction(true);
ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver);
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#if MECH(DELTA) || MECH(SCARA)
#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;
active_driver = active_extruder = target_extruder;
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#endif
// Tell the planner the new "current position"
#if MECH(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();
// Move to the "old position" (move the extruder into place)
if (IsRunning()) prepare_move();
#endif // !DELTA
// Move to the old position if 'F' was in the parameters
if (IsRunning()) prepare_move();
}
#if ENABLED(EXT_SOLENOID)
......@@ -8275,7 +8485,7 @@ void process_next_command() {
switch(command_code) {
case 'G': switch (codenum) {
// G0 -> G1
// G0, G1
case 0:
case 1:
gcode_G0_G1(codenum == 1); break;
......@@ -8307,14 +8517,17 @@ void process_next_command() {
case 10: // G10: retract
case 11: // G11: retract_recover
gcode_G10_G11(codenum == 10); break;
#endif //FWRETRACT
#endif // FWRETRACT
case 28: //G28: Home all axes, one at a time
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.
gcode_G29(); break;
#endif
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#if HASNT(Z_PROBE_SLED)
case 30: // G30 Single Z Probe
gcode_G30(); break;
......@@ -8716,6 +8929,13 @@ void process_next_command() {
case 410: // M410 quickstop - Abort all the planned moves.
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
gcode_M428(); break;
......@@ -8838,16 +9058,7 @@ void clamp_to_software_endstops(float target[3]) {
NOLESS(target[X_AXIS], sw_endstop_min[X_AXIS]);
NOLESS(target[Y_AXIS], sw_endstop_min[Y_AXIS]);
#if !ENABLED(LASERBEAM)
float negative_z_offset = 0;
#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);
NOLESS(target[Z_AXIS], sw_endstop_min[Z_AXIS]);
#endif
}
......@@ -8884,7 +9095,88 @@ static void report_current_position() {
ECHO_E;
#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)
FORCE_INLINE void prevent_dangerous_extrude(float &curr_e, float &dest_e) {
......@@ -9035,9 +9327,14 @@ static void report_current_position() {
// 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])
line_to_destination();
else
line_to_destination(feedrate * feedrate_multiplier / 100.0);
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);
#endif
}
return true;
}
......
......@@ -376,11 +376,13 @@
* CoreXY or CoreYX or CoreXZ or CoreZX
*/
#if MECH(COREXY) || MECH(COREYX)
#define CORE_AXIS_1 A_AXIS
#define CORE_AXIS_2 B_AXIS
#define CORE_AXIS_3 Z_AXIS
#define NORMAL_AXIS Z_AXIS
#elif MECH(COREXZ) || MECH(COREZX)
#define CORE_AXIS_1 A_AXIS
#define CORE_AXIS_2 C_AXIS
#define CORE_AXIS_3 Y_AXIS
#define NORMAL_AXIS Y_AXIS
#endif
/**
......
......@@ -116,6 +116,8 @@
#define SERIAL_Z_PROBE "z_probe: "
#define SERIAL_E_MIN "e_min: "
#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_M119_REPORT "Reporting endstop status"
#define SERIAL_ENDSTOP_HIT "TRIGGERED"
......
......@@ -45,15 +45,11 @@
#define MSG_AUTO_HOME_X "Home X"
#define MSG_AUTO_HOME_Y "Home Y"
#define MSG_AUTO_HOME_Z "Home Z"
#define MSG_MBL_SETTING "Manual Bed Leveling"
#define MSG_MBL_BUTTON " Press the button "
#define MSG_MBL_INTRO " Leveling bed... "
#define MSG_MBL_1 " Adjust first point "
#define MSG_MBL_2 " Adjust second point"
#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_LEVEL_BED_HOMING "Homing XYZ"
#define MSG_LEVEL_BED_WAITING "Click to Begin"
#define MSG_LEVEL_BED_NEXT_POINT "Next Point"
#define MSG_LEVEL_BED_DONE "Leveling Done!"
#define MSG_LEVEL_BED_CANCEL "Cancel"
#define MSG_SET_HOME_OFFSETS "Set home offsets"
#define MSG_SET_ORIGIN "Set origin"
#define MSG_ONFOR "On x:"
......@@ -83,6 +79,7 @@
#define MSG_SPEED "Speed"
#define MSG_NOZZLE "Nozzle"
#define MSG_BED "Bed"
#define MSG_BED_Z "Bed Z"
#define MSG_FAN_SPEED "Fan speed"
#define MSG_FLOW "Flow"
#define MSG_CONTROL "Control"
......
......@@ -42,15 +42,10 @@
#define MSG_AUTOSTART "Autostart"
#define MSG_DISABLE_STEPPERS "Disabilita Motori"
#define MSG_AUTO_HOME "Auto Home"
#define MSG_MBL_SETTING "Liv. piatto manuale "
#define MSG_MBL_BUTTON " Premi il tasto "
#define MSG_MBL_INTRO " Liv. piatto... "
#define MSG_MBL_1 " Calibra il primo punto"
#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_LEVEL_BED_HOMING "Home assi XYZ"
#define MSG_LEVEL_BED_WAITING "Premi per iniziare"
#define MSG_LEVEL_BED_DONE "Livel. terminato!"
#define MSG_LEVEL_BED_CANCEL "Annulla"
#define MSG_SET_HOME_OFFSETS "Setta offset home"
#define MSG_SET_ORIGIN "Imposta Origine"
#define MSG_ONFOR "On x:"
......@@ -76,10 +71,11 @@
#define MSG_EXTRUDE "Estrudi"
#define MSG_RETRACT "Ritrai"
#define MSG_PURGE "Purge"
#define MSG_LEVEL_BED "Liv. piatto"
#define MSG_LEVEL_BED "Livella piano"
#define MSG_SPEED "Velocita"
#define MSG_NOZZLE "Ugello"
#define MSG_BED "Piatto"
#define MSG_BED_Z "piatto Z"
#define MSG_FAN_SPEED "Ventola"
#define MSG_FLOW "Flusso"
#define MSG_CONTROL "Controllo"
......
/**
* MK & MK4due 3D Printer Firmware
*
......@@ -23,7 +24,6 @@
/**
* laser.cpp - Laser control library for Arduino using 16 bit timers- Version 1
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -32,7 +32,7 @@
*
* This library 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
......@@ -58,16 +58,16 @@
void timer3_init(int pin) {
#if ENABLED(LASER_PULSE_METHOD)
TCCR3A = 0; // clear control register A
TCCR3B = pulsebit(WGM33); // set mode as phase and frequency correct pwm, stop the timer
TCCR3B = pulsebit(WGM33); // set mode as phase and frequency correct pwm, stop the timer
ICR3 = F_CPU / LASER_PWM / 2; // the counter runs backwards after TOP
ICR3 = F_CPU / LASER_PWM / 2; // the counter runs backwards after TOP
TCCR3B &= ~(bit(CS30) | bit(CS31) | bit(CS32)); // Stop timer
TCCR3A |= pulsebit(COM3A1); // Connect pin5 to timer register
DDRE |= pulsebit(PORTE3); // Actually output on pin 5
TCCR3A |= pulsebit(COM3A1); // Connect pin5 to timer register
DDRE |= pulsebit(PORTE3); // Actually output on pin 5
OCR3A = 0; // Zero duty cycle = OFF
TCCR3B |= pulsebit(CS30); // No prescaler, start timer
OCR3A = 0; // Zero duty cycle = OFF
TCCR3B |= pulsebit(CS30); // No prescaler, start timer
// Use timer4 to end laser pulse
/*
......@@ -162,20 +162,20 @@
void timer4_init(int pin) {
pinMode(pin, OUTPUT);
analogWrite(pin, 1); // let Arduino setup do it's thing to the PWM pin
TCCR4B = 0x00; // stop Timer4 clock for register updates
TCCR4A = 0x82; // Clear OC4A on match, fast PWM mode, lower WGM4x=14
ICR4 = labs(F_CPU / LASER_PWM); // clock cycles per PWM pulse
OCR4A = labs(F_CPU / LASER_PWM) - 1; // ICR4 - 1 force immediate compare on next tick
TCCR4B = 0x18 | 0x01; // upper WGM4x = 14, clock sel = prescaler, start running
noInterrupts();
TCCR4B &= 0xf8; // stop timer, OC4A may be active now
TCNT4 = labs(F_CPU / LASER_PWM); // force immediate compare on next tick
ICR4 = labs(F_CPU / LASER_PWM); // set new PWM period
TCCR4B |= 0x01; // start the timer with proper prescaler value
interrupts();
analogWrite(pin, 1); // let Arduino setup do it's thing to the PWM pin
TCCR4B = 0x00; // stop Timer4 clock for register updates
TCCR4A = 0x82; // Clear OC4A on match, fast PWM mode, lower WGM4x=14
ICR4 = labs(F_CPU / LASER_PWM); // clock cycles per PWM pulse
OCR4A = labs(F_CPU / LASER_PWM) - 1; // ICR4 - 1 force immediate compare on next tick
TCCR4B = 0x18 | 0x01; // upper WGM4x = 14, clock sel = prescaler, start running
noInterrupts();
TCCR4B &= 0xf8; // stop timer, OC4A may be active now
TCNT4 = labs(F_CPU / LASER_PWM); // force immediate compare on next tick
ICR4 = labs(F_CPU / LASER_PWM); // set new PWM period
TCCR4B |= 0x01; // start the timer with proper prescaler value
interrupts();
}
#endif // LASER_PULSE_METHOD
......@@ -305,7 +305,7 @@
#if ENABLED(LASER_PERIPHERALS)
bool laser_peripherals_ok() { return !digitalRead(LASER_PERIPHERALS_STATUS_PIN); }
void laser_peripherals_on() {
digitalWrite(LASER_PERIPHERALS_PIN, LOW);
if (laser.diagnostics)
......@@ -335,6 +335,7 @@
}
}
}
#endif // LASER_PERIPHERALS
#endif // LASERBEAM
......@@ -23,7 +23,6 @@
/**
* laser.cpp - Laser control library for Arduino using 16 bit timers- Version 1
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -32,7 +31,7 @@
*
* This library 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
......
......@@ -137,7 +137,7 @@
#define LCD_WIDTH_EDIT 22
#endif
#if DISABLED(TALL_FONT_CORRECTION)
#ifndef TALL_FONT_CORRECTION
#define TALL_FONT_CORRECTION 0
#endif
......@@ -158,7 +158,10 @@
U8GLIB_LM6059 u8g(DOGLCD_CS, DOGLCD_A0);
#elif ENABLED(U8GLIB_SSD1306)
// 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)
// The MINIPanel display
U8GLIB_MINI12864 u8g(DOGLCD_CS, DOGLCD_A0);
......@@ -167,10 +170,10 @@
U8GLIB_DOGM128 u8g(DOGLCD_CS, DOGLCD_A0); // HW-SPI Com: CS, A0
#endif
#if DISABLED(LCD_PIXEL_WIDTH)
#ifndef LCD_PIXEL_WIDTH
#define LCD_PIXEL_WIDTH 128
#endif
#if DISABLED(LCD_PIXEL_HEIGHT)
#ifndef LCD_PIXEL_HEIGHT
#define LCD_PIXEL_HEIGHT 64
#endif
......@@ -269,7 +272,7 @@ static void lcd_implementation_init() {
if (show_bootscreen) {
u8g.drawBitmapP(offx, offy, START_BMPBYTEWIDTH, START_BMPHEIGHT, start_bmp);
lcd_setFont(FONT_MENU);
#if DISABLED(STRING_SPLASH_LINE2)
#ifndef STRING_SPLASH_LINE2
u8g.drawStr(txt1X, u8g.getHeight() - (DOG_CHAR_HEIGHT), STRING_SPLASH_LINE1);
#else
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
bool encoderRateMultiplierEnabled;
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 plaPreheatHPBTemp;
int plaPreheatFanSpeed;
......@@ -158,10 +153,7 @@ static void lcd_status_screen();
#if MECH(DELTA)
static void lcd_delta_calibrate_menu();
#elif !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0
static void lcd_level_bed();
static void config_lcd_level_bed();
#endif // !DELTA
#endif
/* Different types of actions that can be used in menu items. */
static void menu_action_back();
......@@ -350,7 +342,6 @@ menuPosition menu_history[10];
uint8_t menu_history_depth = 0;
millis_t next_lcd_update_ms;
uint8_t lcd_status_update_delay;
bool ignore_click = false;
bool wait_for_unclick;
bool defer_return_to_status = false;
......@@ -631,12 +622,6 @@ static void lcd_main_menu() {
END_MENU();
}
#if ENABLED(SDSUPPORT) && ENABLED(MENU_ADDAUTOSTART)
static void lcd_autostart_sd() {
card.checkautostart(true);
}
#endif
/**
*
* "Tune" submenu items
......@@ -665,21 +650,21 @@ void lcd_set_home_offsets() {
#if MECH(COREXY) || MECH(COREYX)|| MECH(COREXZ) || MECH(COREZX)
#if ENABLED(BABYSTEP_XY)
switch(axis) {
case X_AXIS: // X on CoreXY, Core YX, CoreXZ and CoreZZ
babystepsTodo[A_AXIS] += distance * 2;
case CORE_AXIS_1: // X on CoreXY, Core YX, CoreXZ and CoreZZ
babystepsTodo[CORE_AXIS_1] += distance * 2;
babystepsTodo[CORE_AXIS_2] += distance * 2;
break;
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;
break;
case CORE_AXIS_3: // Z on CoreXY and CoreYX, Y on CoreXZ and CoreZX
babystepsTodo[CORE_AXIS_3] += distance;
case NORMAL_AXIS: // Z on CoreXY and CoreYX, Y on CoreXZ and CoreZX
babystepsTodo[NORMAL_AXIS] += distance;
break;
}
#elif MECH(COREXZ) || MECH(COREZX)
babystepsTodo[A_AXIS] += distance * 2;
babystepsTodo[C_AXIS] -= distance * 2;
babystepsTodo[CORE_AXIS_1] += distance * 2;
babystepsTodo[CORE_AXIS_2] -= distance * 2;
#else
babystepsTodo[Z_AXIS] += distance;
#endif
......@@ -771,6 +756,11 @@ static void lcd_tune_menu() {
//
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:
//
......@@ -1027,6 +1017,210 @@ void lcd_cooldown() {
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
......@@ -1068,8 +1262,8 @@ static void lcd_prepare_menu() {
MENU_ITEM(gcode, MSG_LEVEL_BED,
axis_homed[X_AXIS] && axis_homed[Y_AXIS] ? PSTR("G29") : PSTR("G28\nG29")
);
#elif !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0
MENU_ITEM(submenu, MSG_MBL_SETTING, config_lcd_level_bed);
#elif ENABLED(MANUAL_BED_LEVELING)
MENU_ITEM(submenu, MSG_LEVEL_BED, lcd_level_bed);
#endif
//
......@@ -1157,14 +1351,13 @@ static void lcd_prepare_menu() {
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();
if (encoderPosition != 0) {
if (encoderPosition && movesplanned() <= 3) {
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_MAX_ENDSTOPS) NOMORE(current_position[axis], max);
encoderPosition = 0;
line_to_current(axis);
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
}
......@@ -1174,15 +1367,15 @@ static void _lcd_move(const char* name, AxisEnum axis, int min, int max) {
}
#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 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_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_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_Y), Y_AXIS, max(sw_endstop_min[Y_AXIS], -clip), min(sw_endstop_max[Y_AXIS], clip)); }
#else
static void lcd_move_x() { _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, X_MIN_POS, X_MAX_POS); }
static void lcd_move_y() { _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, Y_MIN_POS, Y_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, sw_endstop_min[Y_AXIS], sw_endstop_max[Y_AXIS]); }
#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(
#if EXTRUDERS > 1
uint8_t e
......@@ -1193,11 +1386,11 @@ static void lcd_move_e(
unsigned short original_active_extruder = active_extruder;
active_extruder = e;
#endif
if (encoderPosition != 0) {
if (encoderPosition && movesplanned() <= 3) {
#if ENABLED(IDLE_OOZING_PREVENT)
IDLE_OOZING_retract(false);
#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);
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
}
......@@ -1249,10 +1442,10 @@ static void lcd_move_e(
#define _MOVE_XYZ_ALLOWED true
#endif
static void lcd_move_menu_axis() {
static void _lcd_move_menu_axis() {
START_MENU();
MENU_ITEM(back, MSG_MOVE_AXIS);
if (_MOVE_XYZ_ALLOWED) {
MENU_ITEM(submenu, MSG_MOVE_X, lcd_move_x);
MENU_ITEM(submenu, MSG_MOVE_Y, lcd_move_y);
......@@ -1277,15 +1470,15 @@ static void lcd_move_menu_axis() {
static void lcd_move_menu_10mm() {
move_menu_scale = 10.0;
lcd_move_menu_axis();
_lcd_move_menu_axis();
}
static void lcd_move_menu_1mm() {
move_menu_scale = 1.0;
lcd_move_menu_axis();
_lcd_move_menu_axis();
}
static void lcd_move_menu_01mm() {
move_menu_scale = 0.1;
lcd_move_menu_axis();
_lcd_move_menu_axis();
}
/**
......@@ -1640,6 +1833,10 @@ static void lcd_control_motion_menu() {
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
MENU_ITEM_EDIT(float32, MSG_ZPROBE_ZOFFSET, &zprobe_zoffset, -50, 50);
#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(float3, MSG_VXY_JERK, &max_xy_jerk, 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() {
#if HAS(LCD_CONTRAST)
static void lcd_set_contrast() {
ENCODER_DIRECTION_NORMAL();
if (encoderPosition != 0) {
if (encoderPosition) {
#if ENABLED(U8GLIB_LM6059_AF)
lcd_contrast += encoderPosition;
lcd_contrast &= 0xFF;
......@@ -1883,6 +2080,7 @@ static void lcd_control_motion_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)
uint16_t fileCnt = card.getnrfilenames();
START_MENU();
......@@ -2092,14 +2290,14 @@ static void lcd_control_motion_menu() {
currentMenu = menu_edit_callback_ ## _name; \
callbackFunc = callback; \
}
menu_edit_type(int, int3, itostr3, 1)
menu_edit_type(float, float3, ftostr3, 1)
menu_edit_type(float, float32, ftostr32, 100)
menu_edit_type(float, float43, ftostr43, 1000)
menu_edit_type(float, float5, ftostr5, 0.01)
menu_edit_type(float, float51, ftostr51, 10)
menu_edit_type(float, float52, ftostr52, 100)
menu_edit_type(unsigned long, long5, ftostr5, 0.01)
menu_edit_type(int, int3, itostr3, 1);
menu_edit_type(float, float3, ftostr3, 1);
menu_edit_type(float, float32, ftostr32, 100);
menu_edit_type(float, float43, ftostr43, 1000);
menu_edit_type(float, float5, ftostr5, 0.01);
menu_edit_type(float, float51, ftostr51, 10);
menu_edit_type(float, float52, ftostr52, 100);
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();
}
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
......@@ -2212,7 +2410,7 @@ static void menu_action_function(menuFunc_t func) { (*func)(); }
#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) {
menu_action_setting_edit_bool(pstr, ptr);
(*callback)();
......@@ -2249,10 +2447,16 @@ void lcd_init() {
WRITE(SHIFT_LD, HIGH);
#endif
#ifdef RIGIDBOT_PANEL
#if BUTTON_EXISTS(UP)
SET_INPUT(BTN_UP);
#endif
#if BUTTON_EXISTS(DWN)
SET_INPUT(BTN_DWN);
#endif
#if BUTTON_EXISTS(LFT)
SET_INPUT(BTN_LFT);
#endif
#if BUTTON_EXISTS(RT)
SET_INPUT(BTN_RT);
#endif
......@@ -2274,7 +2478,7 @@ void lcd_init() {
#endif // !NEWPANEL
#if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
pinMode(SD_DETECT_PIN, INPUT);
SET_INPUT(SD_DETECT_PIN);
PULLUP(SD_DETECT_PIN, HIGH);
lcd_sd_status = 2; // UNKNOWN
#endif
......@@ -2428,7 +2632,7 @@ void lcd_update() {
int32_t encoderMovementSteps = abs(encoderDiff) / ENCODER_PULSES_PER_STEP;
if (lastEncoderMovementMillis != 0) {
// Note that the rate is always calculated between to passes through the
// Note that the rate is always calculated between to passes through the
// loop and that the abs of the encoderDiff value is tracked.
float encoderStepRate = (float)(encoderMovementSteps) / ((float)(ms - lastEncoderMovementMillis)) * 1000.0;
......@@ -2455,11 +2659,16 @@ void lcd_update() {
}
#endif // ULTIPANEL
// Simply redraw the Info Screen 10 times a second
if (currentMenu == lcd_status_screen && !(++lcd_status_update_delay % 10))
// We arrive here every ~100ms when idling often enough.
// 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;
}
if (lcdDrawUpdate) {
switch (lcdDrawUpdate) {
case LCDVIEW_CALL_NO_REDRAW:
lcdDrawUpdate = LCDVIEW_NONE;
......@@ -2492,11 +2701,7 @@ void lcd_update() {
#if ENABLED(ULTIPANEL)
// Return to Status Screen after a timeout
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
)
if (currentMenu == lcd_status_screen || defer_return_to_status)
return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
else if (ELAPSED(ms, return_to_status_ms))
lcd_return_to_status();
......@@ -2527,7 +2732,7 @@ void lcd_finishstatus(bool persist = false) {
#if !(ENABLED(LCD_PROGRESS_BAR) && (PROGRESS_MSG_EXPIRE > 0))
UNUSED(persist);
#endif
#if ENABLED(LCD_PROGRESS_BAR)
progress_bar_ms = millis();
#if PROGRESS_MSG_EXPIRE > 0
......@@ -2559,14 +2764,14 @@ bool lcd_hasstatus() { return (lcd_status_message[0] != '\0'); }
void lcd_setstatus(const char* message, bool persist) {
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);
lcd_finishstatus(persist);
}
void lcd_setstatuspgm(const char* message, uint8_t 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);
lcd_status_message_level = level;
lcd_finishstatus(level > 0);
......@@ -2629,32 +2834,46 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
#if BUTTON_EXISTS(EN2)
if (BUTTON_PRESSED(EN2)) newbutton |= EN_B;
#endif
#if ENABLED(RIGIDBOT_PANEL) || BUTTON_EXISTS(ENC)
#if LCD_HAS_DIRECTIONAL_BUTTONS || BUTTON_EXISTS(ENC)
millis_t now = millis();
#endif
#if ENABLED(RIGIDBOT_PANEL)
#if LCD_HAS_DIRECTIONAL_BUTTONS
if (ELAPSED(now, next_button_update_ms)) {
if (BUTTON_PRESSED(UP)) {
encoderDiff = -(ENCODER_STEPS_PER_MENU_ITEM);
next_button_update_ms = now + 300;
}
else if (BUTTON_PRESSED(DWN)) {
encoderDiff = ENCODER_STEPS_PER_MENU_ITEM;
next_button_update_ms = now + 300;
}
else if (BUTTON_PRESSED(LFT)) {
encoderDiff = -(ENCODER_PULSES_PER_STEP);
next_button_update_ms = now + 300;
}
else if (BUTTON_PRESSED(RT)) {
encoderDiff = ENCODER_PULSES_PER_STEP;
next_button_update_ms = now + 300;
if (false) {
// for the else-ifs below
}
#if BUTTON_EXISTS(UP)
else if (BUTTON_PRESSED(UP)) {
encoderDiff = -(ENCODER_STEPS_PER_MENU_ITEM);
next_button_update_ms = now + 300;
}
#endif
#if BUTTON_EXISTS(DWN)
else if (BUTTON_PRESSED(DWN)) {
encoderDiff = ENCODER_STEPS_PER_MENU_ITEM;
next_button_update_ms = now + 300;
}
#endif
#if BUTTON_EXISTS(LFT)
else if (BUTTON_PRESSED(LFT)) {
encoderDiff = -(ENCODER_PULSES_PER_STEP);
next_button_update_ms = now + 300;
}
#endif
#if BUTTON_EXISTS(RT)
else if (BUTTON_PRESSED(RT)) {
encoderDiff = ENCODER_PULSES_PER_STEP;
next_button_update_ms = now + 300;
}
#endif
}
#endif
#if BUTTON_EXISTS(ENC)
if (ELAPSED(now, next_button_update_ms) && BUTTON_PRESSED(ENC)) newbutton |= EN_C;
#endif
buttons = newbutton;
#if ENABLED(LCD_HAS_SLOW_BUTTONS)
buttons |= slow_buttons;
......@@ -2662,7 +2881,7 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
#if ENABLED(REPRAPWORLD_KEYPAD)
GET_BUTTON_STATES(buttons_reprapworld_keypad);
#endif
#else //read it from the shift register
#else
GET_BUTTON_STATES(buttons);
#endif //!NEWPANEL
......@@ -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
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) {
//sprintf(conv,"%5.1f",x);
int xx = x;
......@@ -2724,7 +2943,7 @@ char* itostr2(const uint8_t& x) {
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) {
int xx = abs(x * 10);
conv[0] = (x >= 0) ? '+' : '-';
......@@ -2737,7 +2956,7 @@ char* ftostr31(const float& x) {
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) {
int xx = abs(x * 10);
conv[0] = (xx / 1000) % 10 + '0';
......@@ -2749,8 +2968,8 @@ char* ftostr31ns(const float& x) {
return conv;
}
// Convert float to string with 123.45 format
char* ftostr32(const float& x) {
// Convert signed float to string with 023.45 / -23.45 format
char *ftostr32(const float& x) {
long xx = abs(x * 100);
conv[0] = x >= 0 ? (xx / 10000) % 10 + '0' : '-';
conv[1] = (xx / 1000) % 10 + '0';
......@@ -2762,23 +2981,27 @@ char* ftostr32(const float& x) {
return conv;
}
// Convert float to string with 1.234 format
char* ftostr43(const float& x) {
// Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
char* ftostr43(const float& x, char plus/*=' '*/) {
long xx = x * 1000;
if (xx >= 0)
conv[0] = (xx / 1000) % 10 + '0';
else
if (xx == 0)
conv[0] = ' ';
else if (xx > 0)
conv[0] = plus;
else {
xx = -xx;
conv[0] = '-';
xx = abs(xx);
conv[1] = '.';
conv[2] = (xx / 100) % 10 + '0';
conv[3] = (xx / 10) % 10 + '0';
conv[4] = (xx) % 10 + '0';
conv[5] = 0;
}
conv[1] = (xx / 1000) % 10 + '0';
conv[2] = '.';
conv[3] = (xx / 100) % 10 + '0';
conv[4] = (xx / 10) % 10 + '0';
conv[5] = (xx) % 10 + '0';
conv[6] = 0;
return conv;
}
// Convert float to string with 1.23 format
// Convert unsigned float to string with 1.23 format
char* ftostr12ns(const float& x) {
long xx = x * 100;
xx = abs(xx);
......@@ -2790,11 +3013,12 @@ char* ftostr12ns(const float& x) {
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) {
long xx = abs(x * 100);
long xx = x * 100;
uint8_t dig;
if (x < 0) { // negative val = -_0
if (xx < 0) { // negative val = -_0
xx = -xx;
conv[0] = '-';
dig = (xx / 1000) % 10;
conv[1] = dig ? '0' + dig : ' ';
......@@ -2855,7 +3079,7 @@ char* itostr3sign(const int& x) {
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) {
int xx = x;
if (xx < 0) {
......@@ -2871,38 +3095,38 @@ char* itostr3(const int& x) {
return conv;
}
// Convert int to lj string with 123 format
char* itostr3left(const int& xx) {
if (xx >= 100) {
conv[0] = (xx / 100) % 10 + '0';
conv[1] = (xx / 10) % 10 + '0';
conv[2] = xx % 10 + '0';
// Convert unsigned int to lj string with 123 format
char* itostr3left(const int& x) {
if (x >= 100) {
conv[0] = (x / 100) % 10 + '0';
conv[1] = (x / 10) % 10 + '0';
conv[2] = x % 10 + '0';
conv[3] = 0;
}
else if (xx >= 10) {
conv[0] = (xx / 10) % 10 + '0';
conv[1] = xx % 10 + '0';
else if (x >= 10) {
conv[0] = (x / 10) % 10 + '0';
conv[1] = x % 10 + '0';
conv[2] = 0;
}
else {
conv[0] = xx % 10 + '0';
conv[0] = x % 10 + '0';
conv[1] = 0;
}
return conv;
}
// Convert int to rj string with 1234 format
char* itostr4(const int& xx) {
conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
conv[3] = xx % 10 + '0';
// Convert unsigned int to rj string with 1234 format
char* itostr4(const int& x) {
conv[0] = x >= 1000 ? (x / 1000) % 10 + '0' : ' ';
conv[1] = x >= 100 ? (x / 100) % 10 + '0' : ' ';
conv[2] = x >= 10 ? (x / 10) % 10 + '0' : ' ';
conv[3] = x % 10 + '0';
conv[4] = 0;
return conv;
}
// Convert int to rj string with _123, -123, _-12, or __-1 format
char* itostr4sign(const int& x) {
// Convert signed int to rj string with _123, -123, _-12, or __-1 format
char *itostr4sign(const int& x) {
int xx = abs(x);
int sign = 0;
if (xx >= 100) {
......@@ -2925,49 +3149,7 @@ char* itostr4sign(const int& x) {
return conv;
}
char* ltostr7(const long& xx) {
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
// Convert unsigned float to rj string with 12345 format
char* ftostr5(const float& x) {
long xx = abs(x);
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
......@@ -2979,7 +3161,7 @@ char* ftostr5(const float& x) {
return conv;
}
// Convert float to string with +1234.5 format
// Convert signed float to string with +1234.5 format
char* ftostr51(const float& x) {
long xx = abs(x * 10);
conv[0] = (x >= 0) ? '+' : '-';
......@@ -2993,7 +3175,7 @@ char* ftostr51(const float& x) {
return conv;
}
// Convert float to string with +123.45 format
// Convert signed float to string with +123.45 format
char* ftostr52(const float& x) {
conv[0] = (x >= 0) ? '+' : '-';
long xx = abs(x * 100);
......@@ -3007,67 +3189,37 @@ char* ftostr52(const float& x) {
return conv;
}
#if !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0
static void lcd_level_bed() {
switch(pageShowInfo) {
case 0:
{
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_INTRO));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON));
}
break;
case 1:
{
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_1));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON));
}
break;
case 2:
{
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_2));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON));
}
break;
case 3:
{
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_3));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON));
}
break;
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
char* ltostr7(const long& x) {
if (x >= 1000000)
conv[0]=(x/1000000)%10+'0';
else
conv[0]=' ';
if (x >= 100000)
conv[1]=(x/100000)%10+'0';
else
conv[1]=' ';
if (x >= 10000)
conv[2]=(x/10000)%10+'0';
else
conv[2]=' ';
if (x >= 1000)
conv[3]=(x/1000)%10+'0';
else
conv[3]=' ';
if (x >= 100)
conv[4]=(x/100)%10+'0';
else
conv[4]=' ';
if (x >= 10)
conv[5]=(x/10)%10+'0';
else
conv[5]=' ';
conv[6]=(x)%10+'0';
conv[7]=0;
return conv;
}
#endif //ULTRA_LCD
#endif // ULTRA_LCD
#if ENABLED(SDSUPPORT) && ENABLED(SD_SETTINGS)
void set_sd_dot() {
......
......@@ -55,10 +55,6 @@
void lcd_setcontrast(uint8_t value);
#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_ALERTMESSAGEPGM(x) lcd_setalertstatuspgm(PSTR(x))
......@@ -102,7 +98,7 @@
#endif
void lcd_quick_feedback(); // Audible feedback for a button click - could also be visual
bool lcd_clicked();
void lcd_ignore_click(bool b = true);
void lcd_ignore_click(bool b=true);
bool lcd_blink();
#if ENABLED(ULTIPANEL) && ENABLED(REPRAPWORLD_KEYPAD)
......@@ -138,6 +134,7 @@
#endif // ULTIPANEL && REPRAPWORLD_KEYPAD
#if ENABLED(NEWPANEL)
#define EN_C (_BV(BLEN_C))
#define EN_B (_BV(BLEN_B))
#define EN_A (_BV(BLEN_A))
......@@ -179,25 +176,23 @@
char* itostr2(const uint8_t& x);
char* itostr3sign(const int& x);
char* itostr3(const int& xx);
char* itostr3left(const int& xx);
char* itostr4(const int& xx);
char* itostr3(const int& x);
char* itostr3left(const int& x);
char* itostr4(const int& x);
char* itostr4sign(const int& x);
char* ltostr7(const long& xx);
char* ftostr3(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* ftostr31(const float& x);
char* ftostr32(const float& x);
char* ftostr43(const float& x);
char* ftostr12ns(const float& x);
char* ftostr43(const float& x, char plus=' ');
char* ftostr12ns(const float& x);
char* ftostr32sp(const float& x); // remove zero-padding from ftostr32
char* ftostr5(const float& x);
char* ftostr51(const float& x);
char* ftostr52(const float& x);
char* ltostr7(const long& x);
#elif DISABLED(NEXTION)
......
......@@ -416,7 +416,7 @@ static void lcd_implementation_init(
#elif ENABLED(LCD_I2C_TYPE_MCP23017)
lcd.setMCPType(LTI_TYPE_MCP23017);
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)
lcd.setMCPType(LTI_TYPE_MCP23008);
......@@ -990,14 +990,14 @@ void lcd_implementation_drawedit(const char* pstr, const char* value = NULL) {
static uint8_t ledsprev = 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 HOTENDS > 1
if (target_temperature[1] > 0) leds |= LED_C;
if (degTargetHotend(1) > 0) leds |= LED_C;
#endif
if (leds != ledsprev) {
......
......@@ -12,11 +12,11 @@
*
* 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
* 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/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
......@@ -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
u8g_Delay(15); //delay for CGRAM clear
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); //set x = 0
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_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
ST7920_WRITE_BYTE(0x80 | 8); //x=64
}
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++;
}
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
#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_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
#define UTF_MAPPER_H
......@@ -50,7 +72,7 @@
// ヰ ヱ ヲ ン フ ? ? ? ? ? ヲ ・ ー ヽ ヽ ?
};
#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
#elif ENABLED(DISPLAY_CHARSET_HD44780_WESTERN)
......@@ -84,7 +106,7 @@
// p c T y Ф x Ч ч Ш Щ Ъ Ы b Э Ю Я
};
#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
#elif ENABLED(DISPLAY_CHARSET_HD44780_CYRILLIC)
......@@ -94,30 +116,30 @@
// except 0401 --> 0xa2 = Ё, 0451 --> 0xb5 = ё
const PROGMEM uint8_t utf_recode[] =
{ 0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4, // unicode U+0400 to U+047f
// A Б->Ё B Г Д E Ж З // 0 Ѐ Ё Ђ Ѓ Є Ѕ І Ї
// A Б->Ё B Г Д E Ж З // 0 Ѐ Ё Ђ Ѓ Є Ѕ І Ї
0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f,0xa8, // Ј Љ Њ Ћ Ќ Ѝ Ў Џ
// И Й K Л M H O П // 1 А Б В Г Д Е Ж З
// И Й K Л M H O П // 1 А Б В Г Д Е Ж З
0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab, // И Й К Л М Н О П
// P C T У Ф X Ч ч // 2 Р С Т У Ф Х Г Ч
// P C T У Ф X Ч ч // 2 Р С Т У Ф Х Г Ч
0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1, // Ш Щ Ъ Ы Ь Э Ю Я
// Ш Щ Ъ Ы b Э Ю Я // 3 а б в г д е ж з
// Ш Щ Ъ Ы b Э Ю Я // 3 а б в г д е ж з
0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7, // и й к л м н о п
// a б->ё в г д e ж з // 4 р с т у ф х ц ч
// a б->ё в г д e ж з // 4 р с т у ф х ц ч
0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f,0xbe, // ш щ ъ ы ь э ю я
// и й к л м н o п // 5 ѐ ё ђ ѓ є ѕ і ї
// и й к л м н o п // 5 ѐ ё ђ ѓ є ѕ і ї
0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0, // ј љ њ ћ ќ ѝ ў џ
// p c т y ф x ц ч // 6 Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ
// p c т y ф x ц ч // 6 Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ
0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7 // Ѫ ѩ Ѫ ѫ Ѭ ѭ Ѯ ѯ
// ш щ ъ ы ь э ю я // 7 Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ
// ш щ ъ ы ь э ю я // 7 Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ
}; // ѻ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ
#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)
#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
#else
#error("Something went wrong in the selection of DISPLAY_CHARSET_HD44780's");
#endif // DISPLAY_CHARSET_HD44780_CYRILLIC
#error "Something went wrong in the setting of DISPLAY_CHARSET_HD44780"
#endif // DISPLAY_CHARSET_HD44780
#endif // SIMULATE_ROMFONT
#if ENABLED(MAPPER_NON)
......@@ -209,7 +231,7 @@
}
else if (seen_d5) {
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));
#else
HARDWARE_CHAR_OUT((char)(0xa0u + (utf_hi_char << 6) + d)) ;
......@@ -245,7 +267,7 @@
}
else if (seen_e3 && seen_82_83) {
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));
#else
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 @@
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() {
enable_globally(
#if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
......@@ -41,7 +69,7 @@ Endstops::Endstops() {
#endif
);
enable(true);
#if ENABLED(HAS_Z_PROBE)
#if HAS(Z_PROBE)
enable_z_probe(false);
#endif
} // Endstops::Endstops
......@@ -240,8 +268,8 @@ void Endstops::update() {
#if MECH(COREXY) || MECH(COREYX)|| MECH(COREXZ) || MECH(COREZX)
// Head direction in -X axis for CoreXY and CoreXZ bots.
// If Delta1 == -Delta2, 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 DeltaA == -DeltaB, the movement is only in Y or Z 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(X_HEAD))
#else
if (motor_direction(X_AXIS)) // stepping along -X axis (regular Cartesian bot)
......@@ -274,8 +302,8 @@ void Endstops::update() {
#if MECH(COREXY) || MECH(COREYX)
// Head direction in -Y axis for CoreXY bots.
// If DeltaX == DeltaY, 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 DeltaA == DeltaB, the movement is only in X 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))
#else
if (motor_direction(Y_AXIS)) // -direction
......@@ -296,8 +324,8 @@ void Endstops::update() {
#if MECH(COREXZ) || MECH(COREZX)
// Head direction in -Z axis for CoreXZ bots.
// If DeltaX == DeltaZ, 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 DeltaA == DeltaB, the movement is only in X 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))
#else
if (motor_direction(Z_AXIS))
......
......@@ -33,25 +33,15 @@ class Endstops {
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)
uint16_t current_endstop_bits = 0,
old_endstop_bits = 0;
static uint16_t
#else
byte current_endstop_bits = 0,
old_endstop_bits = 0;
static byte
#endif
bool enabled = true;
bool enabled_globally =
#if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
false
#else
true
#endif
;
current_endstop_bits, old_endstop_bits;
Endstops();
......@@ -63,40 +53,40 @@ class Endstops {
/**
* 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.
*/
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
*/
void M119();
static void M119();
// 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
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
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
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
#if ENABLED(HAS_Z_PROBE)
volatile bool z_probe_enabled = false;
FORCE_INLINE void enable_z_probe(bool onoff = true) { z_probe_enabled = onoff; }
#if HAS(Z_PROBE)
static volatile bool z_probe_enabled;
static void enable_z_probe(bool onoff = true) { z_probe_enabled = onoff; }
#endif
private:
#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
};
......
......@@ -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);
}
// 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) {
unsigned long initial_rate = ceil(block->nominal_rate * entry_factor),
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
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) {
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
} // 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() {
uint8_t block_index = block_buffer_head;
//Make a local copy of block_buffer_tail, because the interrupt can alter it
CRITICAL_SECTION_START;
unsigned char tail = block_buffer_tail;
CRITICAL_SECTION_END
if (movesplanned() > 3) {
if (BLOCK_MOD(block_buffer_head - tail + BLOCK_BUFFER_SIZE) > 3) { // moves queued
block_index = BLOCK_MOD(block_buffer_head - 3);
block_t* block[3] = { NULL, NULL, NULL };
while (block_index != tail) {
block_index = prev_block_index(block_index);
//Make a local copy of block_buffer_tail, because the interrupt can alter it
CRITICAL_SECTION_START;
uint8_t tail = block_buffer_tail;
CRITICAL_SECTION_END
uint8_t b = BLOCK_MOD(block_buffer_head - 3);
while (b != tail) {
b = prev_block_index(b);
block[2] = block[1];
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]);
}
}
......@@ -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() {
uint8_t block_index = block_buffer_tail;
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[1] = block[2];
block[2] = &block_buffer[block_index];
block[2] = &block_buffer[b];
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);
}
// 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
// updating the blocks.
/**
* Recalculate the trapezoid speed profiles for all blocks in the plan
* according to the entry_factor for each junction. Must be called by
* recalculate() after updating the blocks.
*/
void planner_recalculate_trapezoids() {
int8_t block_index = block_buffer_tail;
block_t* current;
......@@ -410,34 +420,42 @@ void plan_init() {
}
#endif //AUTOTEMP
/**
* Maintain fans, paste extruder pressure,
*/
void check_axes_activity() {
unsigned char axis_active[NUM_AXIS] = { 0 },
tail_fan_speed = fanSpeed;
#if ENABLED(BARICUDA)
unsigned char tail_valve_pressure = ValvePressure,
tail_e_to_p_pressure = EtoPPressure;
#endif
block_t* block;
if (blocks_queued()) {
uint8_t block_index = block_buffer_tail;
tail_fan_speed = block_buffer[block_index].fan_speed;
tail_fan_speed = block_buffer[block_buffer_tail].fan_speed;
block_t* block;
#if ENABLED(BARICUDA)
block = &block_buffer[block_index];
block = &block_buffer[block_buffer_tail];
tail_valve_pressure = block->valve_pressure;
tail_e_to_p_pressure = block->e_to_p_pressure;
#endif
while (block_index != block_buffer_head) {
block = &block_buffer[block_index];
for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
block = &block_buffer[b];
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_Y && !axis_active[Y_AXIS]) disable_y();
if (DISABLE_Z && !axis_active[Z_AXIS]) disable_z();
#if DISABLED(LASERBEAM)
if (DISABLE_Z && !axis_active[Z_AXIS]) disable_z();
#endif
if (DISABLE_E && !axis_active[E_AXIS]) {
disable_e0();
disable_e1();
......@@ -455,19 +473,24 @@ void check_axes_activity() {
fan_kick_end = ms + FAN_KICKSTART_TIME;
tail_fan_speed = 255;
}
else if (fan_kick_end > ms)
// Fan still spinning up.
tail_fan_speed = 255;
}
else {
fan_kick_end = 0;
if (PENDING(ms, fan_kick_end)) {
// Fan still spinning up.
tail_fan_speed = 255;
}
}
}
else {
fan_kick_end = 0;
}
#endif //FAN_KICKSTART_TIME
#if ENABLED(FAN_MIN_PWM)
#define CALC_FAN_SPEED (tail_fan_speed ? ( FAN_MIN_PWM + (tail_fan_speed * (255 - (FAN_MIN_PWM))) / 255 ) : 0)
#else
#define CALC_FAN_SPEED tail_fan_speed
#endif // FAN_MIN_PWM
#if ENABLED(FAN_SOFT_PWM)
fanSpeedSoftPwm = CALC_FAN_SPEED;
#else
......@@ -487,14 +510,19 @@ void check_axes_activity() {
analogWrite(HEATER_2_PIN, tail_e_to_p_pressure);
#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
// 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.
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
/**
* Planner::buffer_line
*
* Add a new linear movement to the buffer.
*
* 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)
#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)
......@@ -517,14 +545,16 @@ float junction_deviation = 0.1;
// Rest here until there is room in the buffer.
while (block_buffer_tail == next_buffer_head) idle();
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#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(bed_level_matrix, x, y, z);
#endif
// The target position of the tool 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
int32_t target[NUM_AXIS] = {
long target[NUM_AXIS] = {
lround(x * axis_steps_per_unit[X_AXIS]),
lround(y * axis_steps_per_unit[Y_AXIS]),
lround(z * axis_steps_per_unit[Z_AXIS]),
......@@ -542,23 +572,10 @@ float junction_deviation = 0.1;
}
#endif
int32_t dx = target[X_AXIS] - position[X_AXIS],
dy = target[Y_AXIS] - position[Y_AXIS],
dz = target[Z_AXIS] - position[Z_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
long dx = target[X_AXIS] - position[X_AXIS],
dy = target[Y_AXIS] - position[Y_AXIS],
dz = target[Z_AXIS] - position[Z_AXIS],
de = target[E_AXIS] - position[E_AXIS];
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
if (de) {
......@@ -596,6 +613,20 @@ float junction_deviation = 0.1;
// Mark block as not busy (Not executed by the stepper interrupt)
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
#if MECH(COREXY) || MECH(COREYX)
// corexy planning
......@@ -873,6 +904,7 @@ float junction_deviation = 0.1;
block->laser_duration = laser.duration;
block->laser_status = laser.status;
block->laser_mode = laser.mode;
// 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
// 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;
// Calculate and limit speed in mm/sec for each 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++) {
current_speed[i] = delta_mm[i] * inverse_second;
float cs = fabs(current_speed[i]), mf = max_feedrate[i];
......@@ -1057,6 +1089,9 @@ float junction_deviation = 0.1;
#endif
#if 0 // Use old jerk for now
float junction_deviation = 0.1;
// Compute path unit vector
double unit_vec[3];
......@@ -1194,13 +1229,15 @@ float junction_deviation = 0.1;
*
* 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));
//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);
//inverse.debug("in plan_get inverse");
position.apply_rotation(inverse);
//position.debug("after rotation");
......@@ -1213,13 +1250,15 @@ float junction_deviation = 0.1;
*
* 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)
#else
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);
#endif
......
......@@ -12,11 +12,11 @@
*
* 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
* 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/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
......@@ -33,11 +33,11 @@
*
* Grbl 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
* 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 Grbl. If not, see <http://www.gnu.org/licenses/>.
* along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
// This module is to be considered a sub-module of stepper.c. Please don't include
......@@ -127,29 +127,43 @@ void check_axes_activity();
// Get the number of buffered moves
extern volatile unsigned char block_buffer_head;
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); }
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#if ENABLED(AUTO_BED_LEVELING_FEATURE) || ENABLED(MESH_BED_LEVELING)
#include "vector_3.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
// Transform required to compensate for bed level
extern matrix_3x3 plan_bed_level_matrix;
#include "vector_3.h"
/**
* Get the position applying the bed level matrix
*/
vector_3 plan_get_position();
// Transform to compensate for bed level
extern matrix_3x3 plan_bed_level_matrix;
/**
* The corrected position, applying the bed level matrix
*/
vector_3 plan_adjusted_position();
#endif
/**
* Add a new linear movement to the buffer. x, y, z are the signed, absolute target position in
* millimeters. Feed rate specifies the (target) speed of the motion.
* Add a new linear movement to the buffer.
*
* 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);
/**
* Set the planner positions. Used for G92 instructions.
* Multiplies by axis_steps_per_unit[] to set stepper positions.
* Set the planner.position and individual 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.
*/
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
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);
#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);
//===========================================================================
......@@ -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_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); }
// 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() {
if (blocks_queued())
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() {
if (blocks_queued()) {
block_t* block = &block_buffer[block_buffer_tail];
......
......@@ -1104,14 +1104,14 @@ long st_get_position(uint8_t axis) {
float st_get_axis_position_mm(AxisEnum axis) {
float axis_pos;
#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;
long pos1 = count_position[A_AXIS],
long pos1 = count_position[CORE_AXIS_1],
pos2 = count_position[CORE_AXIS_2];
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 -> (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
axis_pos = st_get_position(axis);
......@@ -1160,10 +1160,10 @@ void endstop_triggered(AxisEnum axis) {
#if MECH(COREXY) || MECH(COREYX) || MECH(COREXZ) || MECH(COREZX)
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;
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;
#else // ! COREXY || COREYX || COREXZ || COREZX
......
......@@ -530,6 +530,27 @@
#if DISABLED(SOFTWARE_MAX_ENDSTOPS)
#error DEPENDENCY ERROR: Missing setting SOFTWARE_MAX_ENDSTOPS
#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_GRID)
#if DISABLED(MIN_PROBE_EDGE)
......@@ -1924,4 +1945,12 @@
#error DEPENDENCY ERROR: You have to set SLED_PIN to a valid pin if you enable Z_PROBE_SLED
#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
......@@ -51,7 +51,7 @@
#define K2 (1.0 - K1)
#endif
#if ENABLED(PIDTEMPBED) || ENABLED(PIDTEMP) || ENABLED(PIDTEMPCHAMBER) || ENABLED(PIDTEMPCOOLER)
#if ENABLED(PIDTEMPBED) || ENABLED(PIDTEMP) || ENABLED(PIDTEMPCHAMBER) || ENABLED(PIDTEMPCOOLER)
#define PID_dT ((OVERSAMPLENR * 14.0)/(F_CPU / 64.0 / 256.0))
#endif
......
......@@ -48,6 +48,7 @@ Added Hysteresis and Z-Wobble correction (only cartesian printers).
Added support reader TAG width MFRC522
Added Cooler and Hot Chamber
Added Laser beam and raster base64
Addes Mesh Bed Level (MBL)
## 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