♻️ More updates for multi-axis

Based on #23112

Co-Authored-By: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
DerAndere 2022-04-01 07:10:38 +02:00 committed by Scott Lahteine
parent 1e3fe65b9d
commit d5a79c27fe
23 changed files with 169 additions and 131 deletions

View file

@ -350,7 +350,7 @@
#define _LIST_N(N,V...) LIST_##N(V) #define _LIST_N(N,V...) LIST_##N(V)
#define LIST_N(N,V...) _LIST_N(N,V) #define LIST_N(N,V...) _LIST_N(N,V)
#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K) #define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
#define ARRAY_N(N,V...) { _LIST_N(N,V) } #define ARRAY_N(N,V...) { _LIST_N(N,V) }
#define ARRAY_N_1(N,K) { LIST_N_1(N,K) } #define ARRAY_N_1(N,K) { LIST_N_1(N,K) }

View file

@ -66,6 +66,12 @@ struct IF<true, L, R> { typedef L type; };
#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K) #define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K)
#define XYZ_GANG(V...) GANG_N(PRIMARY_LINEAR_AXES, V)
#define XYZ_CODE(V...) CODE_N(PRIMARY_LINEAR_AXES, V)
#define SECONDARY_AXIS_GANG(V...) GANG_N(SECONDARY_AXES, V)
#define SECONDARY_AXIS_CODE(V...) CODE_N(SECONDARY_AXES, V)
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
#define LIST_ITEM_E(N) , N #define LIST_ITEM_E(N) , N
#define CODE_ITEM_E(N) ; N #define CODE_ITEM_E(N) ; N

View file

@ -77,11 +77,14 @@ public:
// in the range 0-100 while avoiding rounding artifacts // in the range 0-100 while avoiding rounding artifacts
constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; } constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; }
// Axis names for G-code parsing, reports, etc.
const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME); const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME);
const xyze_char_t iaxis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', 'I', 'J', 'K');
#if LINEAR_AXES <= XYZ #if LINEAR_AXES <= XYZ
#define AXIS_CHAR(A) ((char)('X' + A)) #define AXIS_CHAR(A) ((char)('X' + A))
#define IAXIS_CHAR AXIS_CHAR
#else #else
const xyze_char_t iaxis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', 'I', 'J', 'K');
#define AXIS_CHAR(A) axis_codes[A] #define AXIS_CHAR(A) axis_codes[A]
#define IAXIS_CHAR(A) iaxis_codes[A]
#endif #endif

View file

@ -460,9 +460,11 @@ void GcodeSuite::G28() {
} }
#endif #endif
TERN_(HAS_I_AXIS, if (doI) homeaxis(I_AXIS)); SECONDARY_AXIS_CODE(
TERN_(HAS_J_AXIS, if (doJ) homeaxis(J_AXIS)); if (doI) homeaxis(I_AXIS),
TERN_(HAS_K_AXIS, if (doK) homeaxis(K_AXIS)); if (doJ) homeaxis(J_AXIS),
if (doK) homeaxis(K_AXIS)
);
sync_plan_position(); sync_plan_position();

View file

@ -88,7 +88,7 @@
enum side_t : uint8_t { enum side_t : uint8_t {
TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES, TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES,
LIST_N(DOUBLE(SUB3(LINEAR_AXES)), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM) LIST_N(DOUBLE(SECONDARY_AXES), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM)
}; };
static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER; static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER;

View file

@ -57,7 +57,7 @@ void GcodeSuite::M425() {
LOOP_LINEAR_AXES(a) { LOOP_LINEAR_AXES(a) {
if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) { if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) {
planner.synchronize(); planner.synchronize();
backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_linear_units() : backlash.get_measurement(AxisEnum(a))); backlash.set_distance_mm((AxisEnum)a, parser.has_value() ? parser.value_axis_units((AxisEnum)a) : backlash.get_measurement((AxisEnum)a));
noArgs = false; noArgs = false;
} }
} }

View file

@ -174,14 +174,12 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) {
#if HAS_Y_AXIS #if HAS_Y_AXIS
, SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y) , SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y)
#endif #endif
#if HAS_I_AXIS #if SECONDARY_AXES >= 1
, SP_I_STR, LINEAR_UNIT(toolchange_settings.change_point.i) , LIST_N(DOUBLE(SECONDARY_AXES),
#endif SP_I_STR, I_AXIS_UNIT(toolchange_settings.change_point.i),
#if HAS_J_AXIS SP_J_STR, J_AXIS_UNIT(toolchange_settings.change_point.j),
, SP_J_STR, LINEAR_UNIT(toolchange_settings.change_point.j) SP_K_STR, K_AXIS_UNIT(toolchange_settings.change_point.k)
#endif )
#if HAS_K_AXIS
, SP_K_STR, LINEAR_UNIT(toolchange_settings.change_point.k)
#endif #endif
); );
} }

View file

@ -23,6 +23,7 @@
#include "../gcode.h" #include "../gcode.h"
#include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers #include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers
#include "../../lcd/marlinui.h" #include "../../lcd/marlinui.h"
#include "../../module/motion.h" // for e_axis_mask
#include "../../module/stepper.h" #include "../../module/stepper.h"
#if ENABLED(AUTO_BED_LEVELING_UBL) #if ENABLED(AUTO_BED_LEVELING_UBL)
@ -43,7 +44,7 @@ inline stepper_flags_t selected_axis_bits() {
selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e)); selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e));
} }
else else
selected.bits = selected.e_bits(); selected.bits = e_axis_mask;
} }
#endif #endif
selected.bits |= LINEAR_AXIS_GANG( selected.bits |= LINEAR_AXIS_GANG(

View file

@ -45,9 +45,10 @@
* X, Y, Z : Specify axes to move during cleaning. Default: ALL. * X, Y, Z : Specify axes to move during cleaning. Default: ALL.
*/ */
void GcodeSuite::G12() { void GcodeSuite::G12() {
// Don't allow nozzle cleaning without homing first // Don't allow nozzle cleaning without homing first
if (homing_needed_error(linear_bits & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS))) constexpr main_axes_bits_t clean_axis_mask = main_axes_mask & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS);
return; if (homing_needed_error(clean_axis_mask)) return;
#ifdef WIPE_SEQUENCE_COMMANDS #ifdef WIPE_SEQUENCE_COMMANDS
if (!parser.seen_any()) { if (!parser.seen_any()) {

View file

@ -39,7 +39,7 @@
#endif #endif
/** /**
* M907: Set digital trimpot motor current using axis codes X [Y] [Z] [E] * M907: Set digital trimpot motor current using axis codes X [Y] [Z] [I] [J] [K] [E]
* B<current> - Special case for 4th (E) axis * B<current> - Special case for 4th (E) axis
* S<current> - Special case to set first 3 axes * S<current> - Special case to set first 3 axes
*/ */
@ -49,15 +49,15 @@ void GcodeSuite::M907() {
if (!parser.seen("BS" LOGICAL_AXES_STRING)) if (!parser.seen("BS" LOGICAL_AXES_STRING))
return M907_report(); return M907_report();
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.set_digipot_current(i, parser.value_int()); LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper.set_digipot_current(i, parser.value_int());
if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int()); if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int());
if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int()); if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int());
#elif HAS_MOTOR_CURRENT_PWM #elif HAS_MOTOR_CURRENT_PWM
if (!parser.seen( if (!parser.seen(
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K)
"XY" "XY" SECONDARY_AXIS_GANG("I", "J", "K")
#endif #endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
"Z" "Z"
@ -67,8 +67,11 @@ void GcodeSuite::M907() {
#endif #endif
)) return M907_report(); )) return M907_report();
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K)
if (parser.seenval('X') || parser.seenval('Y')) stepper.set_digipot_current(0, parser.value_int()); if (NUM_AXIS_GANG(
parser.seenval('X'), || parser.seenval('Y'), || false,
|| parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K')
)) stepper.set_digipot_current(0, parser.value_int());
#endif #endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int()); if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int());
@ -81,7 +84,7 @@ void GcodeSuite::M907() {
#if HAS_MOTOR_CURRENT_I2C #if HAS_MOTOR_CURRENT_I2C
// this one uses actual amps in floating point // this one uses actual amps in floating point
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) digipot_i2c.set_current(i, parser.value_float()); LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float());
// Additional extruders use B,C,D for channels 4,5,6. // Additional extruders use B,C,D for channels 4,5,6.
// TODO: Change these parameters because 'E' is used. B<index>? // TODO: Change these parameters because 'E' is used. B<index>?
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
@ -95,7 +98,7 @@ void GcodeSuite::M907() {
const float dac_percent = parser.value_float(); const float dac_percent = parser.value_float();
LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent); LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent);
} }
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper_dac.set_current_percent(i, parser.value_float()); LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper_dac.set_current_percent(i, parser.value_float());
#endif #endif
} }
@ -104,15 +107,15 @@ void GcodeSuite::M907() {
void GcodeSuite::M907_report(const bool forReplay/*=true*/) { void GcodeSuite::M907_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS)); report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS));
#if HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_PWM
SERIAL_ECHOLNPGM_P( // PWM-based has 3 values: SERIAL_ECHOLNPGM_P( // PWM-based has 3 values:
PSTR(" M907 X"), stepper.motor_current_setting[0] // X and Y PSTR(" M907 X"), stepper.motor_current_setting[0] // X, Y, (I, J, K)
, SP_Z_STR, stepper.motor_current_setting[1] // Z , SP_Z_STR, stepper.motor_current_setting[1] // Z
, SP_E_STR, stepper.motor_current_setting[2] // E , SP_E_STR, stepper.motor_current_setting[2] // E
); );
#elif HAS_MOTOR_CURRENT_SPI #elif HAS_MOTOR_CURRENT_SPI
SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values: SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values:
LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default) LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default)
SERIAL_CHAR(' ', axis_codes[q]); SERIAL_CHAR(' ', IAXIS_CHAR(q));
SERIAL_ECHO(stepper.motor_current_setting[q]); SERIAL_ECHO(stepper.motor_current_setting[q]);
} }
SERIAL_CHAR(' ', 'B'); // B (maps to E1 by default) SERIAL_CHAR(' ', 'B'); // B (maps to E1 by default)

View file

@ -51,7 +51,7 @@ void GcodeSuite::G60() {
DEBUG_ECHOPGM(STR_SAVED_POS " S", slot, " :"); DEBUG_ECHOPGM(STR_SAVED_POS " S", slot, " :");
const xyze_pos_t &pos = stored_position[slot]; const xyze_pos_t &pos = stored_position[slot];
DEBUG_ECHOLNPGM_P( DEBUG_ECHOLNPGM_P(
LIST_N(DOUBLE(LINEAR_AXES), PSTR(" : X"), pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k) LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k)
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
, SP_E_LBL, pos.e , SP_E_LBL, pos.e
#endif #endif

View file

@ -74,7 +74,9 @@ void GcodeSuite::M125() {
); );
// Lift Z axis // Lift Z axis
if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); #if HAS_Z_AXIS
if (parser.seenval('Z')) park_point.z = parser.linearval('Z');
#endif
#if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA) #if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA)
park_point += hotend_offset[active_extruder]; park_point += hotend_offset[active_extruder];

View file

@ -54,8 +54,11 @@
* *
* E[distance] - Retract the filament this far * E[distance] - Retract the filament this far
* Z[distance] - Move the Z axis by this distance * Z[distance] - Move the Z axis by this distance
* X[position] - Move to this X position, with Y * X[position] - Move to this X position (instead of NOZZLE_PARK_POINT.x)
* Y[position] - Move to this Y position, with X * Y[position] - Move to this Y position (instead of NOZZLE_PARK_POINT.y)
* I[position] - Move to this I position (instead of NOZZLE_PARK_POINT.i)
* J[position] - Move to this J position (instead of NOZZLE_PARK_POINT.j)
* K[position] - Move to this K position (instead of NOZZLE_PARK_POINT.k)
* U[distance] - Retract distance for removal (manual reload) * U[distance] - Retract distance for removal (manual reload)
* L[distance] - Extrude distance for insertion (manual reload) * L[distance] - Extrude distance for insertion (manual reload)
* B[count] - Number of times to beep, -1 for indefinite (if equipped with a buzzer) * B[count] - Number of times to beep, -1 for indefinite (if equipped with a buzzer)
@ -118,25 +121,21 @@ void GcodeSuite::M600() {
// Move XY axes to filament change position or given position // Move XY axes to filament change position or given position
LINEAR_AXIS_CODE( LINEAR_AXIS_CODE(
if (parser.seenval('X')) park_point.x = parser.linearval('X'), if (parser.seenval('X')) park_point.x = parser.value_linear_units(),
if (parser.seenval('Y')) park_point.y = parser.linearval('Y'), if (parser.seenval('Y')) park_point.y = parser.value_linear_units(),
if (parser.seenval('Z')) park_point.z = parser.linearval('Z'), // Lift Z axis if (parser.seenval('Z')) park_point.z = parser.value_linear_units(), // Lift Z axis
if (parser.seenval(AXIS4_NAME)) park_point.i = parser.linearval(AXIS4_NAME), if (parser.seenval('I')) park_point.i = parser.value_linear_units(),
if (parser.seenval(AXIS5_NAME)) park_point.j = parser.linearval(AXIS5_NAME), if (parser.seenval('J')) park_point.j = parser.value_linear_units(),
if (parser.seenval(AXIS6_NAME)) park_point.k = parser.linearval(AXIS6_NAME) if (parser.seenval('K')) park_point.k = parser.value_linear_units()
); );
#if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA) #if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA)
park_point += hotend_offset[active_extruder]; park_point += hotend_offset[active_extruder];
#endif #endif
#if ENABLED(MMU2_MENUS) // Unload filament
// For MMU2, when enabled, reset retract value so it doesn't mess with MMU filament handling // For MMU2, when enabled, reset retract value so it doesn't mess with MMU filament handling
const float unload_length = standardM600 ? -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)) : 0.5f; const float unload_length = standardM600 ? -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)) : 0.5f;
#else
// Unload filament
const float unload_length = -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length));
#endif
const int beep_count = parser.intval('B', -1 const int beep_count = parser.intval('B', -1
#ifdef FILAMENT_CHANGE_ALERT_BEEPS #ifdef FILAMENT_CHANGE_ALERT_BEEPS

View file

@ -137,7 +137,7 @@
/** /**
* M912: Clear TMC stepper driver overtemperature pre-warn flag held by the library * M912: Clear TMC stepper driver overtemperature pre-warn flag held by the library
* Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4 and E[index]. * Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4, A, B, C, and E[index].
* If no axes are given, clear all. * If no axes are given, clear all.
* *
* Examples: * Examples:

View file

@ -168,12 +168,7 @@ void plan_arc(
// Return if the move is near zero // Return if the move is near zero
if (flat_mm < 0.0001f if (flat_mm < 0.0001f
GANG_N(SUB2(LINEAR_AXES), GANG_N(SUB2(LINEAR_AXES), && travel_L < 0.0001f, && travel_I < 0.0001f, && travel_J < 0.0001f, && travel_K < 0.0001f)
&& travel_L < 0.0001f,
&& travel_I < 0.0001f,
&& travel_J < 0.0001f,
&& travel_K < 0.0001f
)
) return; ) return;
// Feedrate for the move, scaled by the feedrate multiplier // Feedrate for the move, scaled by the feedrate multiplier

View file

@ -666,7 +666,7 @@
#endif #endif
/** /**
* Number of Linear Axes (e.g., XYZ) * Number of Linear Axes (e.g., XYZIJK)
* All the logical axes except for the tool (E) axis * All the logical axes except for the tool (E) axis
*/ */
#ifdef LINEAR_AXES #ifdef LINEAR_AXES
@ -821,7 +821,23 @@
#endif #endif
/** /**
* Number of Logical Axes (e.g., XYZE) * Number of Primary Linear Axes (e.g., XYZ)
* X, XY, or XYZ axes. Excluding duplicate axes (X2, Y2. Z2. Z3, Z4)
*/
#if HAS_I_AXIS
#define PRIMARY_LINEAR_AXES 3
#else
#define PRIMARY_LINEAR_AXES LINEAR_AXES
#endif
/**
* Number of Secondary Axes (e.g., IJK)
* All linear/rotational axes between XYZ and E.
*/
#define SECONDARY_AXES SUB3(LINEAR_AXES)
/**
* Number of Logical Axes (e.g., XYZIJKE)
* All the logical axes that can be commanded directly by G-code. * All the logical axes that can be commanded directly by G-code.
* Delta maps stepper-specific values to ABC steppers. * Delta maps stepper-specific values to ABC steppers.
*/ */
@ -1268,6 +1284,29 @@
#define HAS_ETHERNET 1 #define HAS_ETHERNET 1
#endif #endif
// Fallback axis inverting
#ifndef INVERT_X_DIR
#define INVERT_X_DIR false
#endif
#if HAS_Y_AXIS && !defined(INVERT_Y_DIR)
#define INVERT_Y_DIR false
#endif
#if HAS_Z_AXIS && !defined(INVERT_Z_DIR)
#define INVERT_Z_DIR false
#endif
#if HAS_I_AXIS && !defined(INVERT_I_DIR)
#define INVERT_I_DIR false
#endif
#if HAS_J_AXIS && !defined(INVERT_J_DIR)
#define INVERT_J_DIR false
#endif
#if HAS_K_AXIS && !defined(INVERT_K_DIR)
#define INVERT_K_DIR false
#endif
#if HAS_EXTRUDERS && !defined(INVERT_E_DIR)
#define INVERT_E_DIR false
#endif
/** /**
* This setting is also used by M109 when trying to calculate * This setting is also used by M109 when trying to calculate
* a ballpark safe margin to prevent wait-forever situation. * a ballpark safe margin to prevent wait-forever situation.

View file

@ -79,9 +79,9 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
dwin_string.set(); dwin_string.set();
if (blink) if (blink)
dwin_string.add(value); dwin_string.add(value);
else if (!TEST(axis_homed, axis)) else if (!TEST(axes_homed, axis))
while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?'); while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axis_trusted, axis)) else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axes_trusted, axis))
dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" ")); dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" "));
else else
dwin_string.add(value); dwin_string.add(value);
@ -103,11 +103,11 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
if (blink) if (blink)
dwin_string.add(value); dwin_string.add(value);
else { else {
if (!TEST(axis_homed, axis)) if (!TEST(axes_homed, axis))
while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?'); while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
else { else {
#if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) #if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING)
if (!TEST(axis_trusted, axis)) if (!TEST(axes_trusted, axis))
dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" ")); dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" "));
else else
#endif #endif

View file

@ -476,15 +476,11 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s
#if HAS_Z_AXIS #if HAS_Z_AXIS
const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS); const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS);
#endif #endif
#if HAS_I_AXIS SECONDARY_AXIS_CODE(
const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS); const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS),
#endif const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS),
#if HAS_J_AXIS const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS)
const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS); );
#endif
#if HAS_K_AXIS
const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS);
#endif
#if IS_KINEMATIC #if IS_KINEMATIC
if (!position_is_reachable(x, y)) return; if (!position_is_reachable(x, y)) return;
@ -678,11 +674,11 @@ void restore_feedrate_and_scaling() {
// Software Endstops are based on the configured limits. // Software Endstops are based on the configured limits.
#define _AMIN(A) A##_MIN_POS #define _AMIN(A) A##_MIN_POS
#define _AMAX(A) (_AXIS(A) < Z_AXIS ? A##_MAX_BED : A##_MAX_POS) #define _AMAX(A) A##_MAX_POS
soft_endstops_t soft_endstop = { soft_endstops_t soft_endstop = {
true, false, true, false,
{ MAPLIST(_AMIN, MAIN_AXIS_NAMES) }, { MAPLIST(_AMIN, MAIN_AXIS_NAMES) },
{ MAPLIST(_AMAX, MAIN_AXIS_NAMES) } { MAPLIST(_AMAX, MAIN_AXIS_NAMES) },
}; };
/** /**
@ -1291,10 +1287,10 @@ void prepare_line_to_destination() {
#if HAS_ENDSTOPS #if HAS_ENDSTOPS
linear_axis_bits_t axis_homed, axis_trusted; // = 0 main_axes_bits_t axes_homed, axes_trusted; // = 0
linear_axis_bits_t axes_should_home(linear_axis_bits_t axis_bits/*=linear_bits*/) { main_axes_bits_t axes_should_home(main_axes_bits_t axis_bits/*=main_axes_mask*/) {
auto set_should = [](linear_axis_bits_t &b, AxisEnum a) { auto set_should = [](main_axes_bits_t &b, AxisEnum a) {
if (TEST(b, a) && TERN(HOME_AFTER_DEACTIVATE, axis_is_trusted, axis_was_homed)(a)) if (TEST(b, a) && TERN(HOME_AFTER_DEACTIVATE, axis_is_trusted, axis_was_homed)(a))
CBI(b, a); CBI(b, a);
}; };
@ -1306,20 +1302,12 @@ void prepare_line_to_destination() {
return axis_bits; return axis_bits;
} }
bool homing_needed_error(linear_axis_bits_t axis_bits/*=linear_bits*/) { bool homing_needed_error(main_axes_bits_t axis_bits/*=main_axes_mask*/) {
if ((axis_bits = axes_should_home(axis_bits))) { if ((axis_bits = axes_should_home(axis_bits))) {
PGM_P home_first = GET_TEXT(MSG_HOME_FIRST); PGM_P home_first = GET_TEXT(MSG_HOME_FIRST);
char msg[30]; char msg[30];
sprintf_P(msg, home_first, #define _AXIS_CHAR(N) TEST(axis_bits, _AXIS(N)) ? STR_##N : ""
LINEAR_AXIS_LIST( sprintf_P(msg, home_first, MAPLIST(_AXIS_CHAR, MAIN_AXIS_NAMES));
TEST(axis_bits, X_AXIS) ? "X" : "",
TEST(axis_bits, Y_AXIS) ? "Y" : "",
TEST(axis_bits, Z_AXIS) ? "Z" : "",
TEST(axis_bits, I_AXIS) ? STR_I : "",
TEST(axis_bits, J_AXIS) ? STR_J : "",
TEST(axis_bits, K_AXIS) ? STR_K : ""
)
);
SERIAL_ECHO_START(); SERIAL_ECHO_START();
SERIAL_ECHOLN(msg); SERIAL_ECHOLN(msg);
ui.set_status(msg); ui.set_status(msg);

View file

@ -374,38 +374,41 @@ void restore_feedrate_and_scaling();
/** /**
* Homing and Trusted Axes * Homing and Trusted Axes
*/ */
typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t; typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type main_axes_bits_t;
constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1; constexpr main_axes_bits_t main_axes_mask = _BV(LINEAR_AXES) - 1;
typedef IF<(LINEAR_AXES + EXTRUDERS > 8), uint16_t, uint8_t>::type e_axis_bits_t;
constexpr e_axis_bits_t e_axis_mask = (_BV(EXTRUDERS) - 1) << LINEAR_AXES;
void set_axis_is_at_home(const AxisEnum axis); void set_axis_is_at_home(const AxisEnum axis);
#if HAS_ENDSTOPS #if HAS_ENDSTOPS
/** /**
* axis_homed * axes_homed
* Flags that each linear axis was homed. * Flags that each linear axis was homed.
* XYZ on cartesian, ABC on delta, ABZ on SCARA. * XYZ on cartesian, ABC on delta, ABZ on SCARA.
* *
* axis_trusted * axes_trusted
* Flags that the position is trusted in each linear axis. Set when homed. * Flags that the position is trusted in each linear axis. Set when homed.
* Cleared whenever a stepper powers off, potentially losing its position. * Cleared whenever a stepper powers off, potentially losing its position.
*/ */
extern linear_axis_bits_t axis_homed, axis_trusted; extern main_axes_bits_t axes_homed, axes_trusted;
void homeaxis(const AxisEnum axis); void homeaxis(const AxisEnum axis);
void set_axis_never_homed(const AxisEnum axis); void set_axis_never_homed(const AxisEnum axis);
linear_axis_bits_t axes_should_home(linear_axis_bits_t axis_bits=linear_bits); main_axes_bits_t axes_should_home(main_axes_bits_t axes_mask=main_axes_mask);
bool homing_needed_error(linear_axis_bits_t axis_bits=linear_bits); bool homing_needed_error(main_axes_bits_t axes_mask=main_axes_mask);
inline void set_axis_unhomed(const AxisEnum axis) { CBI(axis_homed, axis); } inline void set_axis_unhomed(const AxisEnum axis) { CBI(axes_homed, axis); }
inline void set_axis_untrusted(const AxisEnum axis) { CBI(axis_trusted, axis); } inline void set_axis_untrusted(const AxisEnum axis) { CBI(axes_trusted, axis); }
inline void set_all_unhomed() { axis_homed = axis_trusted = 0; } inline void set_all_unhomed() { axes_homed = axes_trusted = 0; }
inline void set_axis_homed(const AxisEnum axis) { SBI(axis_homed, axis); } inline void set_axis_homed(const AxisEnum axis) { SBI(axes_homed, axis); }
inline void set_axis_trusted(const AxisEnum axis) { SBI(axis_trusted, axis); } inline void set_axis_trusted(const AxisEnum axis) { SBI(axes_trusted, axis); }
inline void set_all_homed() { axis_homed = axis_trusted = linear_bits; } inline void set_all_homed() { axes_homed = axes_trusted = main_axes_mask; }
#else #else
constexpr linear_axis_bits_t axis_homed = linear_bits, axis_trusted = linear_bits; // Zero-endstop machines are always homed and trusted constexpr main_axes_bits_t axes_homed = main_axes_mask, axes_trusted = main_axes_mask; // Zero-endstop machines are always homed and trusted
inline void homeaxis(const AxisEnum axis) {} inline void homeaxis(const AxisEnum axis) {}
inline void set_axis_never_homed(const AxisEnum) {} inline void set_axis_never_homed(const AxisEnum) {}
inline linear_axis_bits_t axes_should_home(linear_axis_bits_t=linear_bits) { return 0; } inline main_axes_bits_t axes_should_home(main_axes_bits_t=main_axes_mask) { return 0; }
inline bool homing_needed_error(linear_axis_bits_t=linear_bits) { return false; } inline bool homing_needed_error(main_axes_bits_t=main_axes_mask) { return false; }
inline void set_axis_unhomed(const AxisEnum axis) {} inline void set_axis_unhomed(const AxisEnum axis) {}
inline void set_axis_untrusted(const AxisEnum axis) {} inline void set_axis_untrusted(const AxisEnum axis) {}
inline void set_all_unhomed() {} inline void set_all_unhomed() {}
@ -414,13 +417,13 @@ void set_axis_is_at_home(const AxisEnum axis);
inline void set_all_homed() {} inline void set_all_homed() {}
#endif #endif
inline bool axis_was_homed(const AxisEnum axis) { return TEST(axis_homed, axis); } inline bool axis_was_homed(const AxisEnum axis) { return TEST(axes_homed, axis); }
inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axis_trusted, axis); } inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axes_trusted, axis); }
inline bool axis_should_home(const AxisEnum axis) { return (axes_should_home() & _BV(axis)) != 0; } inline bool axis_should_home(const AxisEnum axis) { return (axes_should_home() & _BV(axis)) != 0; }
inline bool no_axes_homed() { return !axis_homed; } inline bool no_axes_homed() { return !axes_homed; }
inline bool all_axes_homed() { return linear_bits == (axis_homed & linear_bits); } inline bool all_axes_homed() { return main_axes_mask == (axes_homed & main_axes_mask); }
inline bool homing_needed() { return !all_axes_homed(); } inline bool homing_needed() { return !all_axes_homed(); }
inline bool all_axes_trusted() { return linear_bits == (axis_trusted & linear_bits); } inline bool all_axes_trusted() { return main_axes_mask == (axes_trusted & main_axes_mask); }
void home_if_needed(const bool keeplev=false); void home_if_needed(const bool keeplev=false);

View file

@ -1933,15 +1933,6 @@ bool Planner::_populate_block(
if (db + dc < 0) SBI(dm, B_AXIS); // Motor B direction if (db + dc < 0) SBI(dm, B_AXIS); // Motor B direction
if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
#endif #endif
#if HAS_I_AXIS
if (di < 0) SBI(dm, I_AXIS);
#endif
#if HAS_J_AXIS
if (dj < 0) SBI(dm, J_AXIS);
#endif
#if HAS_K_AXIS
if (dk < 0) SBI(dm, K_AXIS);
#endif
#elif ENABLED(MARKFORGED_XY) #elif ENABLED(MARKFORGED_XY)
if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction
if (db < 0) SBI(dm, B_AXIS); // Motor B direction if (db < 0) SBI(dm, B_AXIS); // Motor B direction
@ -1949,16 +1940,19 @@ bool Planner::_populate_block(
if (da < 0) SBI(dm, A_AXIS); // Motor A direction if (da < 0) SBI(dm, A_AXIS); // Motor A direction
if (db + da < 0) SBI(dm, B_AXIS); // Motor B direction if (db + da < 0) SBI(dm, B_AXIS); // Motor B direction
#else #else
LINEAR_AXIS_CODE( XYZ_CODE(
if (da < 0) SBI(dm, X_AXIS), if (da < 0) SBI(dm, X_AXIS),
if (db < 0) SBI(dm, Y_AXIS), if (db < 0) SBI(dm, Y_AXIS),
if (dc < 0) SBI(dm, Z_AXIS), if (dc < 0) SBI(dm, Z_AXIS)
if (di < 0) SBI(dm, I_AXIS),
if (dj < 0) SBI(dm, J_AXIS),
if (dk < 0) SBI(dm, K_AXIS)
); );
#endif #endif
SECONDARY_AXIS_CODE(
if (di < 0) SBI(dm, I_AXIS),
if (dj < 0) SBI(dm, J_AXIS),
if (dk < 0) SBI(dm, K_AXIS)
);
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
if (de < 0) SBI(dm, E_AXIS); if (de < 0) SBI(dm, E_AXIS);
const float esteps_float = de * e_factor[extruder]; const float esteps_float = de * e_factor[extruder];
@ -2045,16 +2039,19 @@ bool Planner::_populate_block(
steps_dist_mm.a = da * mm_per_step[A_AXIS]; steps_dist_mm.a = da * mm_per_step[A_AXIS];
steps_dist_mm.b = (db - da) * mm_per_step[B_AXIS]; steps_dist_mm.b = (db - da) * mm_per_step[B_AXIS];
#else #else
LINEAR_AXIS_CODE( XYZ_CODE(
steps_dist_mm.a = da * mm_per_step[A_AXIS], steps_dist_mm.a = da * mm_per_step[A_AXIS],
steps_dist_mm.b = db * mm_per_step[B_AXIS], steps_dist_mm.b = db * mm_per_step[B_AXIS],
steps_dist_mm.c = dc * mm_per_step[C_AXIS], steps_dist_mm.c = dc * mm_per_step[C_AXIS]
steps_dist_mm.i = di * mm_per_step[I_AXIS],
steps_dist_mm.j = dj * mm_per_step[J_AXIS],
steps_dist_mm.k = dk * mm_per_step[K_AXIS]
); );
#endif #endif
SECONDARY_AXIS_CODE(
steps_dist_mm.i = di * mm_per_step[I_AXIS],
steps_dist_mm.j = dj * mm_per_step[J_AXIS],
steps_dist_mm.k = dk * mm_per_step[K_AXIS]
);
TERN_(HAS_EXTRUDERS, steps_dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]); TERN_(HAS_EXTRUDERS, steps_dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]);
TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += steps_dist_mm.e); TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += steps_dist_mm.e);
@ -2181,9 +2178,11 @@ bool Planner::_populate_block(
); );
#endif #endif
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
TERN_(HAS_I_AXIS, if (block->steps.i) stepper.enable_axis(I_AXIS)); SECONDARY_AXIS_CODE(
TERN_(HAS_J_AXIS, if (block->steps.j) stepper.enable_axis(J_AXIS)); if (block->steps.i) stepper.enable_axis(I_AXIS),
TERN_(HAS_K_AXIS, if (block->steps.k) stepper.enable_axis(K_AXIS)); if (block->steps.j) stepper.enable_axis(J_AXIS),
if (block->steps.k) stepper.enable_axis(K_AXIS)
);
#endif #endif
// Enable extruder(s) // Enable extruder(s)

View file

@ -274,14 +274,14 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
#if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA) #if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA)
static uint8_t old_trusted; static uint8_t old_trusted;
if (dopause) { if (dopause) {
old_trusted = axis_trusted; old_trusted = axes_trusted;
stepper.disable_axis(X_AXIS); stepper.disable_axis(X_AXIS);
stepper.disable_axis(Y_AXIS); stepper.disable_axis(Y_AXIS);
} }
else { else {
if (TEST(old_trusted, X_AXIS)) stepper.enable_axis(X_AXIS); if (TEST(old_trusted, X_AXIS)) stepper.enable_axis(X_AXIS);
if (TEST(old_trusted, Y_AXIS)) stepper.enable_axis(Y_AXIS); if (TEST(old_trusted, Y_AXIS)) stepper.enable_axis(Y_AXIS);
axis_trusted = old_trusted; axes_trusted = old_trusted;
} }
#endif #endif
if (dopause) safe_delay(_MAX(DELAY_BEFORE_PROBING, 25)); if (dopause) safe_delay(_MAX(DELAY_BEFORE_PROBING, 25));

View file

@ -2812,6 +2812,7 @@ void Stepper::_set_position(const abce_long_t &spos) {
#elif ENABLED(MARKFORGED_YX) #elif ENABLED(MARKFORGED_YX)
count_position.set(spos.a, spos.b - spos.a, spos.c); count_position.set(spos.a, spos.b - spos.a, spos.c);
#endif #endif
SECONDARY_AXIS_CODE(count_position.i = spos.i, count_position.j = spos.j, count_position.k = spos.k);
TERN_(HAS_EXTRUDERS, count_position.e = spos.e); TERN_(HAS_EXTRUDERS, count_position.e = spos.e);
#else #else
// default non-h-bot planning // default non-h-bot planning

View file

@ -250,8 +250,6 @@ typedef struct {
#endif #endif
}; };
}; };
constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; }
constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; }
} stepper_flags_t; } stepper_flags_t;
// All the stepper enable pins // All the stepper enable pins