Commit 7c04d49e authored by Franco (nextime) Lanza's avatar Franco (nextime) Lanza

Merge branch 'master' into nextime

parents 1f98c2b1 5e21bf70
......@@ -128,6 +128,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).
......
......@@ -70,7 +70,7 @@
#define HEATER_3_PIN ORIG_HEATER_3_PIN
#define HEATER_BED_PIN ORIG_HEATER_BED_PIN
#define HEATER_CHAMBER_PIN -1
#define COOLER_PIN -1
#define COOLER_PIN 2
// TEMP pin
#define TEMP_0_PIN ORIG_TEMP_0_PIN
......@@ -108,11 +108,15 @@
#endif
#if ENABLED(LASERBEAM)
#define LASER_PWR_PIN -1
#define LASER_TTL_PIN -1
#if LASER_CONTROL == 1
#define LASER_PWR_PIN 5
#define LASER_TTL_PIN -1
#elif LASER_CONTROL == 2
#define LASER_PWR_PIN 6
#define LASER_TTL_PIN 5
#if ENABLED(LASER_PERIPHERALS)
#define LASER_PERIPHERALS_PIN -1
#define LASER_PERIPHERALS_STATUS_PIN -1
#define LASER_PERIPHERALS_PIN 11
#define LASER_PERIPHERALS_STATUS_PIN 14
#endif
#endif
......@@ -125,7 +129,7 @@
#endif
#if ENABLED(FLOWMETER_SENSOR)
#define FLOWMETER_PIN -1
#define FLOWMETER_PIN 21
#endif
#if ENABLED(POWER_CONSUMPTION)
......
......@@ -70,7 +70,7 @@
#define HEATER_3_PIN ORIG_HEATER_3_PIN
#define HEATER_BED_PIN ORIG_HEATER_BED_PIN
#define HEATER_CHAMBER_PIN -1
#define COOLER_PIN -1
#define COOLER_PIN 2
// TEMP pin
#define TEMP_0_PIN ORIG_TEMP_0_PIN
......@@ -108,11 +108,15 @@
#endif
#if ENABLED(LASERBEAM)
#define LASER_PWR_PIN -1
#define LASER_TTL_PIN -1
#if LASER_CONTROL == 1
#define LASER_PWR_PIN 5
#define LASER_TTL_PIN -1
#elif LASER_CONTROL == 2
#define LASER_PWR_PIN 6
#define LASER_TTL_PIN 5
#if ENABLED(LASER_PERIPHERALS)
#define LASER_PERIPHERALS_PIN -1
#define LASER_PERIPHERALS_STATUS_PIN -1
#define LASER_PERIPHERALS_PIN 11
#define LASER_PERIPHERALS_STATUS_PIN 14
#endif
#endif
......@@ -125,7 +129,7 @@
#endif
#if ENABLED(FLOWMETER_SENSOR)
#define FLOWMETER_PIN -1
#define FLOWMETER_PIN 21
#endif
#if ENABLED(POWER_CONSUMPTION)
......
### 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.
......
......@@ -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))
/**************************************************************************/
/**************************************************************************
......
......@@ -178,6 +178,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
......@@ -337,6 +345,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
......@@ -539,6 +553,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)
......@@ -744,6 +762,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
......
......@@ -171,6 +171,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);
......@@ -7294,6 +7415,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."
......@@ -7959,6 +8121,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))) {
......@@ -7983,10 +8146,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;
}
......@@ -7997,14 +8162,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);
......@@ -8033,12 +8196,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);
......@@ -8071,12 +8233,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;
......@@ -8095,12 +8256,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);
......@@ -8122,12 +8282,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;
......@@ -8140,64 +8299,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);
#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);
}
#if MECH(DELTA) || MECH(SCARA)
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)
......@@ -8274,7 +8482,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;
......@@ -8306,14 +8514,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;
......@@ -8715,6 +8926,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;
......@@ -8837,16 +9055,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
}
......@@ -8883,7 +9092,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) {
......@@ -9034,9 +9324,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;
}
......
......@@ -74,26 +74,6 @@
#define KILL_PIN -1 // 80 with Smart Controller LCD
#define SUICIDE_PIN -1 // PIN that has to be turned on right after start, to keep power flowing.
#undef LASER_TTL_PIN
#undef LASER_PWR_PIN
#if LASER_CONTROL == 1
#define LASER_PWR_PIN 5
#define LASER_TTL_PIN -1
#endif
#if LASER_CONTROL == 2
#define LASER_TTL_PIN 5 // Digital pins 2, 3, 5, 6, 7, 8 are attached to timers we can use
#define LASER_PWR_PIN 2
#endif
#if ENABLED(LASER_PERIPHERALS)
#undef LASER_PERIPHERALS_PIN
#undef LASER_PERIPHERALS_STATUS_PIN
#define LASER_PERIPHERALS_PIN 11
#define LASER_PERIPHERALS_STATUS_PIN 4
#endif
#if ENABLED(ULTRA_LCD)
#define KILL_PIN 80
#if ENABLED(NEWPANEL)
......
......@@ -70,37 +70,6 @@
#define ORIG_HEATER_BED_PIN 8 // BED
#define ORIG_TEMP_BED_PIN 14 // ANALOG NUMBERING
#if ENABLED(LASERBEAM)
#undef LASER_TTL_PIN
#undef LASER_PWR_PIN
#if LASER_CONTROL == 1
#define LASER_PWR_PIN 5
#define LASER_TTL_PIN -1
#endif
#if LASER_CONTROL == 2
#define LASER_TTL_PIN 6 // Digital pins 2, 3, 5, 6, 7, 8 are attached to timers we can use
#define LASER_PWR_PIN 5
#endif
#endif
#if ENABLED(LASER_PERIPHERALS)
#undef LASER_PERIPHERALS_PIN
#undef LASER_PERIPHERALS_STATUS_PIN
#define LASER_PERIPHERALS_PIN 11
#define LASER_PERIPHERALS_STATUS_PIN 4
#endif
#if ENABLED(PIDTEMPCOOLER)
#undef COOLER_PIN
#define COOLER_PIN 2
#endif
#if ENABLED(FLOWMETER_SENSOR)
#undef FLOWMETER_PIN
#define FLOWMETER_PIN 21
#endif
#if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) || ENABLED(G3D_PANEL)
#define KILL_PIN 41
#else
......
......@@ -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
......
<img align="right" src="Documentation/Logo/MarlinKimbra%20Logo%20GitHub.png" />
# MarlinKimbra 3D Printer Firmware for Arduino
## Version 4.2.82 Laser dev
## Version 4.2.84 Laser dev
This is the Laser enhananced version with the patches from Franco (nextime) Lanza.
......@@ -15,6 +15,9 @@ For K40 laser cutter there are branches with the default config files ready to u
* [with cooler and flow sensor](https://git.nexlab.net/machinery/MarlinKimbra/tree/k40_flow_cooler)
* [without cooler and flow sensor](https://git.nexlab.net/machinery/MarlinKimbra/tree/k40_noflow_nocooler)
Also, take care that lasers needs a larger serial buffer on arduino mega 2560 than the default 64 byte buffer, so
take a look at needed modification on the arduino ide from [Laser Documentation README](/Documentation/Laser/README.md)
### Special thanks
* all Marlin8bit-developers.
......@@ -43,24 +46,25 @@ http://marlinkimbra.it
This version of Marlin was made to accommodate some requests made by the community RepRap Italy http://forums.reprap.org/index.php?349
The new features are:
A single Firmware for all types of printers; Cartesian, Delta, SCARA, CoreXY & CoreXZ.
The possibility of having only one hotend independently from the extruders that you have.
The addition of the 6th extruder.
Management Color Mixing Extruder
System Management MKr4 for 6 extruders with just two drivers or only driver.
Management Multyextruder NPr2, 4/6 extruders with only two engines.
Management Dual Extruder DONDOLO.
Adding commands to facilitate purging of hotend.
Step per unit varied for each extruder as well as the feedrate and the acceleration.
Adding Debug Dryrun used by repetier.
Added total Power on time writed in SD CARD.
Added total Power consumption writed in SD CARD.
Added total filament printed writed in SD CARD.
Added anti extruder idle oozing system.
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
- A single Firmware for all types of printers; Cartesian, Delta, SCARA, CoreXY & CoreXZ.
- The possibility of having only one hotend independently from the extruders that you have.
- The addition of the 6th extruder.
- Management Color Mixing Extruder
- System Management MKr4 for 6 extruders with just two drivers or only driver.
- Management Multyextruder NPr2, 4/6 extruders with only two engines.
- Management Dual Extruder DONDOLO.
- Adding commands to facilitate purging of hotend.
- Step per unit varied for each extruder as well as the feedrate and the acceleration.
- Adding Debug Dryrun used by repetier.
- Added total Power on time writed in SD CARD.
- Added total Power consumption writed in SD CARD.
- Added total filament printed writed in SD CARD.
- Added anti extruder idle oozing system.
- 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
- Added 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