0
0
Fork 0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2025-01-31 14:12:52 +00:00

🧑‍💻 Change Marlin DIR bits: 1=Forward, 0=Reverse (#25791)

This commit is contained in:
Scott Lahteine 2023-05-15 22:00:15 -05:00 committed by GitHub
parent 48496dfec1
commit 25ddde0394
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 265 additions and 329 deletions

View file

@ -99,15 +99,15 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
LOOP_NUM_AXES(axis) {
if (distance_mm[axis]) {
const bool reverse = dm[axis];
const bool forward = dm[axis];
// When an axis changes direction, add axis backlash to the residual error
if (changed_dir[axis])
residual_error[axis] += (reverse ? -f_corr : f_corr) * distance_mm[axis] * planner.settings.axis_steps_per_mm[axis];
residual_error[axis] += (forward ? f_corr : -f_corr) * distance_mm[axis] * planner.settings.axis_steps_per_mm[axis];
// Decide how much of the residual error to correct in this segment
int32_t error_correction = residual_error[axis];
if (reverse != (error_correction < 0))
if (forward == (error_correction < 0))
error_correction = 0; // Don't take up any backlash in this segment, as it would subtract steps
#ifdef BACKLASH_SMOOTHING_MM
@ -147,14 +147,14 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
int32_t Backlash::get_applied_steps(const AxisEnum axis) {
if (axis >= NUM_AXES) return 0;
const bool reverse = last_direction_bits[axis];
const bool forward = last_direction_bits[axis];
const int32_t residual_error_axis = residual_error[axis];
// At startup it is assumed the last move was forwards. So the applied
// steps will always be a non-positive number.
if (!reverse) return -residual_error_axis;
if (forward) return -residual_error_axis;
const float f_corr = float(correction) / all_on;
const int32_t full_error_axis = -f_corr * distance_mm[axis] * planner.settings.axis_steps_per_mm[axis];

View file

@ -411,7 +411,7 @@ class FilamentSensorBase {
// Only trigger on extrusion with XYZ movement to allow filament change and retract/recover.
const uint8_t e = b->extruder;
const int32_t steps = b->steps.e;
const float mm = (b->direction_bits.e ? -steps : steps) * planner.mm_per_step[E_AXIS_N(e)];
const float mm = (b->direction_bits.e ? steps : -steps) * planner.mm_per_step[E_AXIS_N(e)];
if (e < NUM_RUNOUT_SENSORS) mm_countdown.runout[e] -= mm;
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
if (e < NUM_MOTION_SENSORS) mm_countdown.motion[e] -= mm;

View file

@ -102,8 +102,10 @@ void GcodeSuite::M493() {
}
switch (val) {
case ftMotionMode_ENABLED: fxdTiCtrl.reset(); break;
#if HAS_X_AXIS
//case ftMotionMode_ULENDO_FBS:
//case ftMotionMode_DISCTF:
// break;
case ftMotionMode_ZV:
case ftMotionMode_ZVD:
case ftMotionMode_EI:
@ -114,9 +116,10 @@ void GcodeSuite::M493() {
fxdTiCtrl.updateShapingA();
fxdTiCtrl.reset();
break;
//case ftMotionMode_ULENDO_FBS:
//case ftMotionMode_DISCTF:
#endif
case ftMotionMode_ENABLED:
fxdTiCtrl.reset();
break;
default: break;
}
}
@ -195,7 +198,7 @@ void GcodeSuite::M493() {
fxdTiCtrl.reset();
if (fxdTiCtrl.cfg_dynFreqMode) { SERIAL_ECHOPGM("Compensator base dynamic frequency (X/A axis) set to:"); }
else { SERIAL_ECHOPGM("Compensator static frequency (X/A axis) set to: "); }
SERIAL_ECHO_F( fxdTiCtrl.cfg_baseFreq[0], 2 );
SERIAL_ECHO_F(fxdTiCtrl.cfg_baseFreq[0], 2);
SERIAL_ECHOLNPGM(".");
}
else { // Frequency out of range.
@ -243,7 +246,7 @@ void GcodeSuite::M493() {
fxdTiCtrl.reset();
if (fxdTiCtrl.cfg_dynFreqMode) { SERIAL_ECHOPGM("Compensator base dynamic frequency (Y/B axis) set to:"); }
else { SERIAL_ECHOPGM("Compensator static frequency (Y/B axis) set to: "); }
SERIAL_ECHO_F( fxdTiCtrl.cfg_baseFreq[1], 2 );
SERIAL_ECHO_F(fxdTiCtrl.cfg_baseFreq[1], 2);
SERIAL_ECHOLNPGM(".");
}
else { // Frequency out of range.

View file

@ -38,10 +38,13 @@ void GcodeSuite::G6() {
planner.last_page_step_rate = parser.value_ulong();
if (!DirectStepping::Config::DIRECTIONAL) {
if (parser.seen('X')) planner.last_page_dir.x = !!parser.value_byte();
if (parser.seen('Y')) planner.last_page_dir.y = !!parser.value_byte();
if (parser.seen('Z')) planner.last_page_dir.z = !!parser.value_byte();
if (parser.seen('E')) planner.last_page_dir.e = !!parser.value_byte();
#define PAGE_DIR_SET(N,A) do{ if (parser.seen(N)) planner.last_page_dir.A = !!parser.value_byte(); } while(0)
LOGICAL_AXIS_CODE(
PAGE_DIR_SET('E',E),
PAGE_DIR_SET('X',X), PAGE_DIR_SET('Y',Y), PAGE_DIR_SET('Z',Z),
PAGE_DIR_SET(AXIS4_NAME,I), PAGE_DIR_SET(AXIS5_NAME,J), PAGE_DIR_SET(AXIS6_NAME,K),
PAGE_DIR_SET(AXIS5_NAME,U), PAGE_DIR_SET(AXIS6_NAME,V), PAGE_DIR_SET(AXIS7_NAME,W)
);
}
// No index means we just set the state

View file

@ -4037,8 +4037,12 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive."
/**
* Fixed-Time Motion limitations
*/
#if ENABLED(FT_MOTION) && (NUM_AXES > 3 || E_STEPPERS > 1 || NUM_Z_STEPPERS > 1 || ANY(DUAL_X_CARRIAGE, HAS_SYNCED_X_STEPPERS, HAS_SYNCED_Y_STEPPERS, HAS_MULTI_EXTRUDER, MIXING_EXTRUDER))
#error "FT_MOTION is currently limited to machines with 3 linear axes and a single extruder."
#if ENABLED(FT_MOTION)
#if NUM_AXES > 3
#error "FT_MOTION is currently limited to machines with 3 linear axes."
#elif ENABLED(MIXING_EXTRUDER)
#error "FT_MOTION is incompatible with MIXING_EXTRUDER."
#endif
#endif
// Multi-Stepping Limit

View file

@ -872,7 +872,7 @@ void Endstops::update() {
#if HAS_X_AXIS
if (stepper.axis_is_moving(X_AXIS)) {
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(X_AXIS_HEAD)) { // -direction
#if USE_X_MIN || (X_SPI_SENSORLESS && X_HOME_TO_MIN)
PROCESS_ENDSTOP_X(MIN);
#if CORE_DIAG(XY, Y, MIN)
@ -905,7 +905,7 @@ void Endstops::update() {
#if HAS_Y_AXIS
if (stepper.axis_is_moving(Y_AXIS)) {
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
#if USE_Y_MIN || (Y_SPI_SENSORLESS && Y_HOME_TO_MIN)
PROCESS_ENDSTOP_Y(MIN);
#if CORE_DIAG(XY, X, MIN)
@ -938,7 +938,7 @@ void Endstops::update() {
#if HAS_Z_AXIS
if (stepper.axis_is_moving(Z_AXIS)) {
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
if (!stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
#if USE_Z_MIN || (Z_SPI_SENSORLESS && Z_HOME_TO_MIN)
if ( TERN1(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, z_probe_enabled)
@ -983,7 +983,7 @@ void Endstops::update() {
#if HAS_I_AXIS
if (stepper.axis_is_moving(I_AXIS)) {
if (stepper.motor_direction(I_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(I_AXIS_HEAD)) { // -direction
#if USE_I_MIN || (I_SPI_SENSORLESS && I_HOME_TO_MIN)
PROCESS_ENDSTOP(I, MIN);
#endif
@ -998,7 +998,7 @@ void Endstops::update() {
#if HAS_J_AXIS
if (stepper.axis_is_moving(J_AXIS)) {
if (stepper.motor_direction(J_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(J_AXIS_HEAD)) { // -direction
#if USE_J_MIN || (J_SPI_SENSORLESS && J_HOME_TO_MIN)
PROCESS_ENDSTOP(J, MIN);
#endif
@ -1013,7 +1013,7 @@ void Endstops::update() {
#if HAS_K_AXIS
if (stepper.axis_is_moving(K_AXIS)) {
if (stepper.motor_direction(K_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(K_AXIS_HEAD)) { // -direction
#if USE_K_MIN || (K_SPI_SENSORLESS && K_HOME_TO_MIN)
PROCESS_ENDSTOP(K, MIN);
#endif
@ -1028,7 +1028,7 @@ void Endstops::update() {
#if HAS_U_AXIS
if (stepper.axis_is_moving(U_AXIS)) {
if (stepper.motor_direction(U_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(U_AXIS_HEAD)) { // -direction
#if USE_U_MIN || (U_SPI_SENSORLESS && U_HOME_TO_MIN)
PROCESS_ENDSTOP(U, MIN);
#endif
@ -1043,7 +1043,7 @@ void Endstops::update() {
#if HAS_V_AXIS
if (stepper.axis_is_moving(V_AXIS)) {
if (stepper.motor_direction(V_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(V_AXIS_HEAD)) { // -direction
#if USE_V_MIN || (V_SPI_SENSORLESS && V_HOME_TO_MIN)
PROCESS_ENDSTOP(V, MIN);
#endif
@ -1058,7 +1058,7 @@ void Endstops::update() {
#if HAS_W_AXIS
if (stepper.axis_is_moving(W_AXIS)) {
if (stepper.motor_direction(W_AXIS_HEAD)) { // -direction
if (!stepper.motor_direction(W_AXIS_HEAD)) { // -direction
#if USE_W_MIN || (W_SPI_SENSORLESS && W_HOME_TO_MIN)
PROCESS_ENDSTOP(W, MIN);
#endif

View file

@ -422,9 +422,9 @@ void FxdTiCtrl::reset() {
stepperCmdBuff_produceIdx = stepperCmdBuff_consumeIdx = 0;
for (uint32_t i = 0U; i < (FTM_BATCH_SIZE); i++) { // Reset trajectory history
TERN_(HAS_X_AXIS, xd[i] = 0.0f);
TERN_(HAS_Y_AXIS, yd[i] = 0.0f);
TERN_(HAS_Z_AXIS, zd[i] = 0.0f);
TERN_(HAS_X_AXIS, xd[i] = 0.0f);
TERN_(HAS_Y_AXIS, yd[i] = 0.0f);
TERN_(HAS_Z_AXIS, zd[i] = 0.0f);
TERN_(HAS_EXTRUDERS, ed[i] = 0.0f);
}
@ -432,23 +432,26 @@ void FxdTiCtrl::reset() {
batchRdy = batchRdyForInterp = false;
runoutEna = false;
TERN_(HAS_X_AXIS, x_endPosn_prevBlock = 0.0f);
TERN_(HAS_Y_AXIS, y_endPosn_prevBlock = 0.0f);
TERN_(HAS_Z_AXIS, z_endPosn_prevBlock = 0.0f);
TERN_(HAS_X_AXIS, x_endPosn_prevBlock = 0.0f);
TERN_(HAS_Y_AXIS, y_endPosn_prevBlock = 0.0f);
TERN_(HAS_Z_AXIS, z_endPosn_prevBlock = 0.0f);
TERN_(HAS_EXTRUDERS, e_endPosn_prevBlock = 0.0f);
makeVector_idx = makeVector_idx_z1 = 0;
makeVector_batchIdx = FTM_BATCH_SIZE;
TERN_(HAS_X_AXIS, x_steps = 0);
TERN_(HAS_Y_AXIS, y_steps = 0);
TERN_(HAS_Z_AXIS, z_steps = 0);
TERN_(HAS_X_AXIS, x_steps = 0);
TERN_(HAS_Y_AXIS, y_steps = 0);
TERN_(HAS_Z_AXIS, z_steps = 0);
TERN_(HAS_EXTRUDERS, e_steps = 0);
interpIdx = interpIdx_z1 = 0;
TERN_(HAS_X_AXIS, x_dirState = stepDirState_NOT_SET);
TERN_(HAS_Y_AXIS, y_dirState = stepDirState_NOT_SET);
TERN_(HAS_Z_AXIS, z_dirState = stepDirState_NOT_SET);
TERN_(HAS_X_AXIS, x_dirState = stepDirState_NOT_SET);
TERN_(HAS_Y_AXIS, y_dirState = stepDirState_NOT_SET);
TERN_(HAS_Z_AXIS, z_dirState = stepDirState_NOT_SET);
TERN_(HAS_EXTRUDERS, e_dirState = stepDirState_NOT_SET);
nextStepTicks = FTM_MIN_TICKS;
#if HAS_X_AXIS
@ -486,28 +489,28 @@ void FxdTiCtrl::loadBlockData(block_t * const current_block) {
#if HAS_X_AXIS
x_startPosn = x_endPosn_prevBlock;
float x_moveDist = current_block->steps.a / planner.settings.axis_steps_per_mm[X_AXIS];
if (direction.x) x_moveDist *= -1.0f;
if (!direction.x) x_moveDist *= -1.0f;
x_Ratio = x_moveDist * oneOverLength;
#endif
#if HAS_Y_AXIS
y_startPosn = y_endPosn_prevBlock;
float y_moveDist = current_block->steps.b / planner.settings.axis_steps_per_mm[Y_AXIS];
if (direction.y) y_moveDist *= -1.0f;
if (!direction.y) y_moveDist *= -1.0f;
y_Ratio = y_moveDist * oneOverLength;
#endif
#if HAS_Z_AXIS
z_startPosn = z_endPosn_prevBlock;
float z_moveDist = current_block->steps.c / planner.settings.axis_steps_per_mm[Z_AXIS];
if (direction.z) z_moveDist *= -1.0f;
if (!direction.z) z_moveDist *= -1.0f;
z_Ratio = z_moveDist * oneOverLength;
#endif
#if HAS_EXTRUDERS
e_startPosn = e_endPosn_prevBlock;
float extrusion = current_block->steps.e / planner.settings.axis_steps_per_mm[E_AXIS_N(current_block->extruder)];
if (direction.e) extrusion *= -1.0f;
if (!direction.e) extrusion *= -1.0f;
e_Ratio = extrusion * oneOverLength;
#endif
@ -568,31 +571,31 @@ void FxdTiCtrl::loadBlockData(block_t * const current_block) {
// One less than (Accel + Coasting + Decel) datapoints
max_intervals = N1 + N2 + N3 - 1U;
TERN_(HAS_X_AXIS, x_endPosn_prevBlock += x_moveDist);
TERN_(HAS_Y_AXIS, y_endPosn_prevBlock += y_moveDist);
TERN_(HAS_Z_AXIS, z_endPosn_prevBlock += z_moveDist);
TERN_(HAS_X_AXIS, x_endPosn_prevBlock += x_moveDist);
TERN_(HAS_Y_AXIS, y_endPosn_prevBlock += y_moveDist);
TERN_(HAS_Z_AXIS, z_endPosn_prevBlock += z_moveDist);
TERN_(HAS_EXTRUDERS, e_endPosn_prevBlock += extrusion);
}
// Generate data points of the trajectory.
void FxdTiCtrl::makeVector() {
float accel_k = 0.0f; // (mm/s^2) Acceleration K factor
float tau = (makeVector_idx + 1) * (FTM_TS); // (s) Time since start of block
float dist = 0.0f; // (mm) Distance traveled
float accel_k = 0.0f; // (mm/s^2) Acceleration K factor
float tau = (makeVector_idx + 1) * (FTM_TS); // (s) Time since start of block
float dist = 0.0f; // (mm) Distance traveled
if (makeVector_idx < N1) {
// Acceleration phase
dist = (f_s * tau) + (0.5f * accel_P * sq(tau)); // (mm) Distance traveled for acceleration phase
accel_k = accel_P; // (mm/s^2) Acceleration K factor from Accel phase
dist = (f_s * tau) + (0.5f * accel_P * sq(tau)); // (mm) Distance traveled for acceleration phase
accel_k = accel_P; // (mm/s^2) Acceleration K factor from Accel phase
}
else if (makeVector_idx >= N1 && makeVector_idx < (N1 + N2)) {
// Coasting phase
dist = s_1e + F_P * (tau - N1 * (FTM_TS)); // (mm) Distance traveled for coasting phase
dist = s_1e + F_P * (tau - N1 * (FTM_TS)); // (mm) Distance traveled for coasting phase
//accel_k = 0.0f;
}
else {
// Deceleration phase
const float tau_ = tau - (N1 + N2) * (FTM_TS); // (s) Time since start of decel phase
const float tau_ = tau - (N1 + N2) * (FTM_TS); // (s) Time since start of decel phase
dist = s_2e + F_P * tau_ + 0.5f * decel_P * sq(tau_); // (mm) Distance traveled for deceleration phase
accel_k = decel_P; // (mm/s^2) Acceleration K factor from Decel phase
}
@ -614,7 +617,7 @@ void FxdTiCtrl::makeVector() {
}
else {
ed[makeVector_batchIdx] = new_raw_z1;
// Alternatively: coordArray_e[makeVector_batchIdx] = e_startDist + extrusion / (N1 + N2 + N3);
// Alternatively: ed[makeVector_batchIdx] = e_startPosn + (e_Ratio * dist) / (N1 + N2 + N3);
}
#endif

View file

@ -169,7 +169,7 @@ float Planner::mm_per_step[DISTINCT_AXES]; // (mm) Millimeters per step
#if ENABLED(DIRECT_STEPPING)
uint32_t Planner::last_page_step_rate = 0;
xyze_bool_t Planner::last_page_dir{0};
AxisBits Planner::last_page_dir; // = 0
#endif
#if HAS_EXTRUDERS
@ -1887,67 +1887,56 @@ bool Planner::_populate_block(
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
, feedRate_t fr_mm_s, const uint8_t extruder, const PlannerHints &hints
) {
int32_t LOGICAL_AXIS_LIST(
de = target.e - position.e,
da = target.a - position.a,
db = target.b - position.b,
dc = target.c - position.c,
di = target.i - position.i,
dj = target.j - position.j,
dk = target.k - position.k,
du = target.u - position.u,
dv = target.v - position.v,
dw = target.w - position.w
);
xyze_long_t dist = target - position;
/* <-- add a slash to enable
SERIAL_ECHOLNPGM(
" _populate_block FR:", fr_mm_s,
#if HAS_X_AXIS
" A:", target.a, " (", da, " steps)"
" A:", target.a, " (", dist.a, " steps)"
#endif
#if HAS_Y_AXIS
" B:", target.b, " (", db, " steps)"
" B:", target.b, " (", dist.b, " steps)"
#endif
#if HAS_Z_AXIS
" C:", target.c, " (", dc, " steps)"
" C:", target.c, " (", dist.c, " steps)"
#endif
#if HAS_I_AXIS
" " STR_I ":", target.i, " (", di, " steps)"
" " STR_I ":", target.i, " (", dist.i, " steps)"
#endif
#if HAS_J_AXIS
" " STR_J ":", target.j, " (", dj, " steps)"
" " STR_J ":", target.j, " (", dist.j, " steps)"
#endif
#if HAS_K_AXIS
" " STR_K ":", target.k, " (", dk, " steps)"
" " STR_K ":", target.k, " (", dist.k, " steps)"
#endif
#if HAS_U_AXIS
" " STR_U ":", target.u, " (", du, " steps)"
" " STR_U ":", target.u, " (", dist.u, " steps)"
#endif
#if HAS_V_AXIS
" " STR_V ":", target.v, " (", dv, " steps)"
" " STR_V ":", target.v, " (", dist.v, " steps)"
#endif
#if HAS_W_AXIS
" " STR_W ":", target.w, " (", dw, " steps)"
" " STR_W ":", target.w, " (", dist.w, " steps)"
#endif
#if HAS_EXTRUDERS
" E:", target.e, " (", de, " steps)"
" E:", target.e, " (", dist.e, " steps)"
#endif
);
//*/
#if EITHER(PREVENT_COLD_EXTRUSION, PREVENT_LENGTHY_EXTRUDE)
if (de) {
if (dist.e) {
#if ENABLED(PREVENT_COLD_EXTRUSION)
if (thermalManager.tooColdToExtrude(extruder)) {
position.e = target.e; // Behave as if the move really took place, but ignore E part
TERN_(HAS_POSITION_FLOAT, position_float.e = target_float.e);
de = 0; // no difference
dist.e = 0; // no difference
SERIAL_ECHO_MSG(STR_ERR_COLD_EXTRUDE_STOP);
}
#endif // PREVENT_COLD_EXTRUSION
#if ENABLED(PREVENT_LENGTHY_EXTRUDE)
const float e_steps = ABS(de * e_factor[extruder]);
const float e_steps = ABS(dist.e * e_factor[extruder]);
const float max_e_steps = settings.axis_steps_per_mm[E_AXIS_N(extruder)] * (EXTRUDE_MAXLENGTH);
if (e_steps > max_e_steps) {
#if ENABLED(MIXING_EXTRUDER)
@ -1962,7 +1951,7 @@ bool Planner::_populate_block(
if (ignore_e) {
position.e = target.e; // Behave as if the move really took place, but ignore E part
TERN_(HAS_POSITION_FLOAT, position_float.e = target_float.e);
de = 0; // no difference
dist.e = 0; // no difference
SERIAL_ECHO_MSG(STR_ERR_LONG_EXTRUDE_STOP);
}
}
@ -1973,49 +1962,49 @@ bool Planner::_populate_block(
// Compute direction bit-mask for this block
AxisBits dm;
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
dm.hx = (da < 0); // Save the toolhead's true direction in X
dm.hy = (db < 0); // ...and Y
TERN_(HAS_Z_AXIS, dm.z = (dc < 0));
dm.hx = (dist.a > 0); // Save the toolhead's true direction in X
dm.hy = (dist.b > 0); // ...and Y
TERN_(HAS_Z_AXIS, dm.z = (dist.c > 0));
#endif
#if IS_CORE
#if CORE_IS_XY
dm.a = (da + db < 0); // Motor A direction
dm.b = (CORESIGN(da - db) < 0); // Motor B direction
dm.a = (dist.a + dist.b > 0); // Motor A direction
dm.b = (CORESIGN(dist.a - dist.b) > 0); // Motor B direction
#elif CORE_IS_XZ
dm.hx = (da < 0); // Save the toolhead's true direction in X
dm.y = (db < 0);
dm.hz = (dc < 0); // ...and Z
dm.a = (da + dc < 0); // Motor A direction
dm.c = (CORESIGN(da - dc) < 0); // Motor C direction
dm.hx = (dist.a > 0); // Save the toolhead's true direction in X
dm.y = (dist.b > 0);
dm.hz = (dist.c > 0); // ...and Z
dm.a = (dist.a + dist.c > 0); // Motor A direction
dm.c = (CORESIGN(dist.a - dist.c) > 0); // Motor C direction
#elif CORE_IS_YZ
dm.x = (da < 0);
dm.hy = (db < 0); // Save the toolhead's true direction in Y
dm.hz = (dc < 0); // ...and Z
dm.b = (db + dc < 0); // Motor B direction
dm.c = (CORESIGN(db - dc) < 0); // Motor C direction
dm.x = (dist.a > 0);
dm.hy = (dist.b > 0); // Save the toolhead's true direction in Y
dm.hz = (dist.c > 0); // ...and Z
dm.b = (dist.b + dist.c > 0); // Motor B direction
dm.c = (CORESIGN(dist.b - dist.c) > 0); // Motor C direction
#endif
#elif ENABLED(MARKFORGED_XY)
dm.a = (da + db < 0); // Motor A direction
dm.b = (db < 0); // Motor B direction
dm.a = (dist.a + dist.b > 0); // Motor A direction
dm.b = (dist.b > 0); // Motor B direction
#elif ENABLED(MARKFORGED_YX)
dm.a = (da < 0); // Motor A direction
dm.b = (db + da < 0); // Motor B direction
dm.a = (dist.a > 0); // Motor A direction
dm.b = (dist.b + dist.a > 0); // Motor B direction
#else
XYZ_CODE(
dm.x = (da < 0),
dm.y = (db < 0),
dm.z = (dc < 0)
dm.x = (dist.a > 0),
dm.y = (dist.b > 0),
dm.z = (dist.c > 0)
);
#endif
SECONDARY_AXIS_CODE(
dm.i = (di < 0), dm.j = (dj < 0), dm.k = (dk < 0),
dm.u = (du < 0), dm.v = (dv < 0), dm.w = (dw < 0)
dm.i = (dist.i > 0), dm.j = (dist.j > 0), dm.k = (dist.k > 0),
dm.u = (dist.u > 0), dm.v = (dist.v > 0), dm.w = (dist.w > 0)
);
#if HAS_EXTRUDERS
dm.e = (de < 0);
const float esteps_float = de * e_factor[extruder];
dm.e = (dist.e > 0);
const float esteps_float = dist.e * e_factor[extruder];
const uint32_t esteps = ABS(esteps_float) + 0.5f;
#else
constexpr uint32_t esteps = 0;
@ -2061,21 +2050,21 @@ bool Planner::_populate_block(
// See https://www.corexy.com/theory.html
block->steps.set(NUM_AXIS_LIST(
#if CORE_IS_XY
ABS(da + db), ABS(da - db), ABS(dc)
ABS(dist.a + dist.b), ABS(dist.a - dist.b), ABS(dist.c)
#elif CORE_IS_XZ
ABS(da + dc), ABS(db), ABS(da - dc)
ABS(dist.a + dist.c), ABS(dist.b), ABS(dist.a - dist.c)
#elif CORE_IS_YZ
ABS(da), ABS(db + dc), ABS(db - dc)
ABS(dist.a), ABS(dist.b + dist.c), ABS(dist.b - dist.c)
#elif ENABLED(MARKFORGED_XY)
ABS(da + db), ABS(db), ABS(dc)
ABS(dist.a + dist.b), ABS(dist.b), ABS(dist.c)
#elif ENABLED(MARKFORGED_YX)
ABS(da), ABS(db + da), ABS(dc)
ABS(dist.a), ABS(dist.b + dist.a), ABS(dist.c)
#elif IS_SCARA
ABS(da), ABS(db), ABS(dc)
ABS(dist.a), ABS(dist.b), ABS(dist.c)
#else // default non-h-bot planning
ABS(da), ABS(db), ABS(dc)
ABS(dist.a), ABS(dist.b), ABS(dist.c)
#endif
, ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw)
, ABS(dist.i), ABS(dist.j), ABS(dist.k), ABS(dist.u), ABS(dist.v), ABS(dist.w)
));
/**
@ -2090,104 +2079,82 @@ bool Planner::_populate_block(
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
struct { float x, y, z; } head;
#endif
} steps_dist_mm;
} dist_mm;
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
steps_dist_mm.head.x = da * mm_per_step[A_AXIS];
steps_dist_mm.head.y = db * mm_per_step[B_AXIS];
TERN_(HAS_Z_AXIS, steps_dist_mm.z = dc * mm_per_step[Z_AXIS]);
dist_mm.head.x = dist.a * mm_per_step[A_AXIS];
dist_mm.head.y = dist.b * mm_per_step[B_AXIS];
TERN_(HAS_Z_AXIS, dist_mm.z = dist.c * mm_per_step[Z_AXIS]);
#endif
#if IS_CORE
#if CORE_IS_XY
steps_dist_mm.a = (da + db) * mm_per_step[A_AXIS];
steps_dist_mm.b = CORESIGN(da - db) * mm_per_step[B_AXIS];
dist_mm.a = (dist.a + dist.b) * mm_per_step[A_AXIS];
dist_mm.b = CORESIGN(dist.a - dist.b) * mm_per_step[B_AXIS];
#elif CORE_IS_XZ
steps_dist_mm.head.x = da * mm_per_step[A_AXIS];
steps_dist_mm.y = db * mm_per_step[Y_AXIS];
steps_dist_mm.head.z = dc * mm_per_step[C_AXIS];
steps_dist_mm.a = (da + dc) * mm_per_step[A_AXIS];
steps_dist_mm.c = CORESIGN(da - dc) * mm_per_step[C_AXIS];
dist_mm.head.x = dist.a * mm_per_step[A_AXIS];
dist_mm.y = dist.b * mm_per_step[Y_AXIS];
dist_mm.head.z = dist.c * mm_per_step[C_AXIS];
dist_mm.a = (dist.a + dist.c) * mm_per_step[A_AXIS];
dist_mm.c = CORESIGN(dist.a - dist.c) * mm_per_step[C_AXIS];
#elif CORE_IS_YZ
steps_dist_mm.x = da * mm_per_step[X_AXIS];
steps_dist_mm.head.y = db * mm_per_step[B_AXIS];
steps_dist_mm.head.z = dc * mm_per_step[C_AXIS];
steps_dist_mm.b = (db + dc) * mm_per_step[B_AXIS];
steps_dist_mm.c = CORESIGN(db - dc) * mm_per_step[C_AXIS];
dist_mm.x = dist.a * mm_per_step[X_AXIS];
dist_mm.head.y = dist.b * mm_per_step[B_AXIS];
dist_mm.head.z = dist.c * mm_per_step[C_AXIS];
dist_mm.b = (dist.b + dist.c) * mm_per_step[B_AXIS];
dist_mm.c = CORESIGN(dist.b - dist.c) * mm_per_step[C_AXIS];
#endif
#elif ENABLED(MARKFORGED_XY)
steps_dist_mm.a = (da - db) * mm_per_step[A_AXIS];
steps_dist_mm.b = db * mm_per_step[B_AXIS];
dist_mm.a = (dist.a - dist.b) * mm_per_step[A_AXIS];
dist_mm.b = dist.b * mm_per_step[B_AXIS];
#elif ENABLED(MARKFORGED_YX)
steps_dist_mm.a = da * mm_per_step[A_AXIS];
steps_dist_mm.b = (db - da) * mm_per_step[B_AXIS];
dist_mm.a = dist.a * mm_per_step[A_AXIS];
dist_mm.b = (dist.b - dist.a) * mm_per_step[B_AXIS];
#else
XYZ_CODE(
steps_dist_mm.a = da * mm_per_step[A_AXIS],
steps_dist_mm.b = db * mm_per_step[B_AXIS],
steps_dist_mm.c = dc * mm_per_step[C_AXIS]
dist_mm.a = dist.a * mm_per_step[A_AXIS],
dist_mm.b = dist.b * mm_per_step[B_AXIS],
dist_mm.c = dist.c * mm_per_step[C_AXIS]
);
#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],
steps_dist_mm.u = du * mm_per_step[U_AXIS],
steps_dist_mm.v = dv * mm_per_step[V_AXIS],
steps_dist_mm.w = dw * mm_per_step[W_AXIS]
dist_mm.i = dist.i * mm_per_step[I_AXIS], dist_mm.j = dist.j * mm_per_step[J_AXIS], dist_mm.k = dist.k * mm_per_step[K_AXIS],
dist_mm.u = dist.u * mm_per_step[U_AXIS], dist_mm.v = dist.v * mm_per_step[V_AXIS], dist_mm.w = dist.w * mm_per_step[W_AXIS]
);
TERN_(HAS_EXTRUDERS, steps_dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]);
TERN_(HAS_EXTRUDERS, 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 += dist_mm.e);
#if HAS_ROTATIONAL_AXES
bool cartesian_move = hints.cartesian_move;
#endif
if (true NUM_AXIS_GANG(
&& block->steps.a < MIN_STEPS_PER_SEGMENT,
&& block->steps.b < MIN_STEPS_PER_SEGMENT,
&& block->steps.c < MIN_STEPS_PER_SEGMENT,
&& block->steps.i < MIN_STEPS_PER_SEGMENT,
&& block->steps.j < MIN_STEPS_PER_SEGMENT,
&& block->steps.k < MIN_STEPS_PER_SEGMENT,
&& block->steps.u < MIN_STEPS_PER_SEGMENT,
&& block->steps.v < MIN_STEPS_PER_SEGMENT,
&& block->steps.w < MIN_STEPS_PER_SEGMENT
&& block->steps.a < MIN_STEPS_PER_SEGMENT, && block->steps.b < MIN_STEPS_PER_SEGMENT, && block->steps.c < MIN_STEPS_PER_SEGMENT,
&& block->steps.i < MIN_STEPS_PER_SEGMENT, && block->steps.j < MIN_STEPS_PER_SEGMENT, && block->steps.k < MIN_STEPS_PER_SEGMENT,
&& block->steps.u < MIN_STEPS_PER_SEGMENT, && block->steps.v < MIN_STEPS_PER_SEGMENT, && block->steps.w < MIN_STEPS_PER_SEGMENT
)
) {
block->millimeters = TERN0(HAS_EXTRUDERS, ABS(steps_dist_mm.e));
block->millimeters = TERN0(HAS_EXTRUDERS, ABS(dist_mm.e));
}
else {
if (hints.millimeters)
block->millimeters = hints.millimeters;
else {
const xyze_pos_t displacement = LOGICAL_AXIS_ARRAY(
steps_dist_mm.e,
dist_mm.e,
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
steps_dist_mm.head.x,
steps_dist_mm.head.y,
steps_dist_mm.z,
dist_mm.head.x, dist_mm.head.y, dist_mm.z,
#elif CORE_IS_XZ
steps_dist_mm.head.x,
steps_dist_mm.y,
steps_dist_mm.head.z,
dist_mm.head.x, dist_mm.y, dist_mm.head.z,
#elif CORE_IS_YZ
steps_dist_mm.x,
steps_dist_mm.head.y,
steps_dist_mm.head.z,
dist_mm.x, dist_mm.head.y, dist_mm.head.z,
#else
steps_dist_mm.x,
steps_dist_mm.y,
steps_dist_mm.z,
dist_mm.x, dist_mm.y, dist_mm.z,
#endif
steps_dist_mm.i,
steps_dist_mm.j,
steps_dist_mm.k,
steps_dist_mm.u,
steps_dist_mm.v,
steps_dist_mm.w
dist_mm.i, dist_mm.j, dist_mm.k,
dist_mm.u, dist_mm.v, dist_mm.w
);
block->millimeters = get_move_distance(displacement OPTARG(HAS_ROTATIONAL_AXES, cartesian_move));
@ -2202,7 +2169,7 @@ bool Planner::_populate_block(
* A correction function is permitted to add steps to an axis, it
* should *never* remove steps!
*/
TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(da, db, dc, dm, block));
TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(dist.a, dist.b, dist.c, dm, block));
}
TERN_(HAS_EXTRUDERS, block->steps.e = esteps);
@ -2279,12 +2246,9 @@ bool Planner::_populate_block(
#endif
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
SECONDARY_AXIS_CODE(
if (block->steps.i) stepper.enable_axis(I_AXIS),
if (block->steps.j) stepper.enable_axis(J_AXIS),
if (block->steps.k) stepper.enable_axis(K_AXIS),
if (block->steps.u) stepper.enable_axis(U_AXIS),
if (block->steps.v) stepper.enable_axis(V_AXIS),
if (block->steps.w) stepper.enable_axis(W_AXIS)
if (block->steps.i) stepper.enable_axis(I_AXIS), if (block->steps.j) stepper.enable_axis(J_AXIS),
if (block->steps.k) stepper.enable_axis(K_AXIS), if (block->steps.u) stepper.enable_axis(U_AXIS),
if (block->steps.v) stepper.enable_axis(V_AXIS), if (block->steps.w) stepper.enable_axis(W_AXIS)
);
#endif
@ -2383,7 +2347,7 @@ bool Planner::_populate_block(
#if ENABLED(FILAMENT_WIDTH_SENSOR)
if (extruder == FILAMENT_SENSOR_EXTRUDER_NUM) // Only for extruder with filament sensor
filwidth.advance_e(steps_dist_mm.e);
filwidth.advance_e(dist_mm.e);
#endif
// Calculate and limit speed in mm/sec (linear) or degrees/sec (rotational)
@ -2393,7 +2357,7 @@ bool Planner::_populate_block(
// Linear axes first with less logic
LOOP_NUM_AXES(i) {
current_speed[i] = steps_dist_mm[i] * inverse_secs;
current_speed[i] = dist_mm[i] * inverse_secs;
const feedRate_t cs = ABS(current_speed[i]),
max_fr = settings.max_feedrate_mm_s[i];
if (cs > max_fr) NOMORE(speed_factor, max_fr / cs);
@ -2402,7 +2366,7 @@ bool Planner::_populate_block(
// Limit speed on extruders, if any
#if HAS_EXTRUDERS
{
current_speed.e = steps_dist_mm.e * inverse_secs;
current_speed.e = dist_mm.e * inverse_secs;
#if HAS_MIXER_SYNC_CHANNEL
// Move all mixing extruders at the specified rate
if (mixer.get_current_vtool() == MIXER_AUTORETRACT_TOOL)
@ -2519,9 +2483,9 @@ bool Planner::_populate_block(
*
* extruder_advance_K[extruder] : There is an advance factor set for this extruder.
*
* de > 0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
* dist.e > 0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
*/
use_advance_lead = esteps && extruder_advance_K[E_INDEX_N(extruder)] && de > 0;
use_advance_lead = esteps && extruder_advance_K[E_INDEX_N(extruder)] && dist.e > 0;
if (use_advance_lead) {
float e_D_ratio = (target_float.e - position_float.e) /
@ -2632,10 +2596,10 @@ bool Planner::_populate_block(
#if HAS_DIST_MM_ARG
cart_dist_mm
#else
LOGICAL_AXIS_ARRAY(steps_dist_mm.e,
steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z,
steps_dist_mm.i, steps_dist_mm.j, steps_dist_mm.k,
steps_dist_mm.u, steps_dist_mm.v, steps_dist_mm.w)
LOGICAL_AXIS_ARRAY(dist_mm.e,
dist_mm.x, dist_mm.y, dist_mm.z,
dist_mm.i, dist_mm.j, dist_mm.k,
dist_mm.u, dist_mm.v, dist_mm.w)
#endif
;
@ -2804,7 +2768,7 @@ bool Planner::_populate_block(
#ifndef TRAVEL_EXTRA_XYJERK
#define TRAVEL_EXTRA_XYJERK 0
#endif
const float extra_xyjerk = TERN0(HAS_EXTRUDERS, de <= 0) ? TRAVEL_EXTRA_XYJERK : 0;
const float extra_xyjerk = TERN0(HAS_EXTRUDERS, dist.e <= 0) ? TRAVEL_EXTRA_XYJERK : 0;
uint8_t limited = 0;
TERN(HAS_LINEAR_E_JERK, LOOP_NUM_AXES, LOOP_LOGICAL_AXES)(i) {
@ -3239,16 +3203,11 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s
block->decelerate_after = block->step_event_count;
// Will be set to last direction later if directional format.
block->direction_bits = 0;
#define PAGE_UPDATE_DIR(AXIS) \
if (!last_page_dir[_AXIS(AXIS)]) SBI(block->direction_bits, _AXIS(AXIS));
block->direction_bits.reset();
if (!DirectStepping::Config::DIRECTIONAL) {
PAGE_UPDATE_DIR(X);
PAGE_UPDATE_DIR(Y);
PAGE_UPDATE_DIR(Z);
PAGE_UPDATE_DIR(E);
#define PAGE_UPDATE_DIR(AXIS) do{ if (last_page_dir.AXIS) block->direction_bits.AXIS = true; }while(0);
LOGICAL_AXIS_MAP(PAGE_UPDATE_DIR);
}
// If this is the first added movement, reload the delay, otherwise, cancel it.

View file

@ -417,7 +417,7 @@ class Planner {
#if ENABLED(DIRECT_STEPPING)
static uint32_t last_page_step_rate; // Last page step rate given
static xyze_bool_t last_page_dir; // Last page direction given
static AxisBits last_page_dir; // Last page direction given, where 1 represents forward or positive motion
#endif
#if HAS_EXTRUDERS

View file

@ -383,111 +383,114 @@ xyze_int8_t Stepper::count_direction{0};
}
#if HAS_SYNCED_X_STEPPERS
#define X_APPLY_DIR(v,Q) do{ X_DIR_WRITE(v); X2_DIR_WRITE(INVERT_DIR(X2_VS_X, v)); }while(0)
#define X_APPLY_DIR(FWD,Q) do{ X_DIR_WRITE(FWD); X2_DIR_WRITE(INVERT_DIR(X2_VS_X, FWD)); }while(0)
#if ENABLED(X_DUAL_ENDSTOPS)
#define X_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(X,v)
#define X_APPLY_STEP(FWD,Q) DUAL_ENDSTOP_APPLY_STEP(X,FWD)
#else
#define X_APPLY_STEP(v,Q) do{ X_STEP_WRITE(v); X2_STEP_WRITE(v); }while(0)
#define X_APPLY_STEP(FWD,Q) do{ X_STEP_WRITE(FWD); X2_STEP_WRITE(FWD); }while(0)
#endif
#elif ENABLED(DUAL_X_CARRIAGE)
#define X_APPLY_DIR(v,ALWAYS) do{ \
if (extruder_duplication_enabled || ALWAYS) { X_DIR_WRITE(v); X2_DIR_WRITE((v) ^ idex_mirrored_mode); } \
else if (last_moved_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \
#define X_APPLY_DIR(FWD,ALWAYS) do{ \
if (extruder_duplication_enabled || ALWAYS) { X_DIR_WRITE(FWD); X2_DIR_WRITE((FWD) ^ idex_mirrored_mode); } \
else if (last_moved_extruder) X2_DIR_WRITE(FWD); else X_DIR_WRITE(FWD); \
}while(0)
#define X_APPLY_STEP(v,ALWAYS) do{ \
if (extruder_duplication_enabled || ALWAYS) { X_STEP_WRITE(v); X2_STEP_WRITE(v); } \
else if (last_moved_extruder) X2_STEP_WRITE(v); else X_STEP_WRITE(v); \
#define X_APPLY_STEP(FWD,ALWAYS) do{ \
if (extruder_duplication_enabled || ALWAYS) { X_STEP_WRITE(FWD); X2_STEP_WRITE(FWD); } \
else if (last_moved_extruder) X2_STEP_WRITE(FWD); else X_STEP_WRITE(FWD); \
}while(0)
#elif HAS_X_AXIS
#define X_APPLY_DIR(v,Q) X_DIR_WRITE(v)
#define X_APPLY_STEP(v,Q) X_STEP_WRITE(v)
#define X_APPLY_DIR(FWD,Q) X_DIR_WRITE(FWD)
#define X_APPLY_STEP(FWD,Q) X_STEP_WRITE(FWD)
#endif
#if HAS_SYNCED_Y_STEPPERS
#define Y_APPLY_DIR(v,Q) do{ Y_DIR_WRITE(v); Y2_DIR_WRITE(INVERT_DIR(Y2_VS_Y, v)); }while(0)
#define Y_APPLY_DIR(FWD,Q) do{ Y_DIR_WRITE(FWD); Y2_DIR_WRITE(INVERT_DIR(Y2_VS_Y, FWD)); }while(0)
#if ENABLED(Y_DUAL_ENDSTOPS)
#define Y_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Y,v)
#define Y_APPLY_STEP(FWD,Q) DUAL_ENDSTOP_APPLY_STEP(Y,FWD)
#else
#define Y_APPLY_STEP(v,Q) do{ Y_STEP_WRITE(v); Y2_STEP_WRITE(v); }while(0)
#define Y_APPLY_STEP(FWD,Q) do{ Y_STEP_WRITE(FWD); Y2_STEP_WRITE(FWD); }while(0)
#endif
#elif HAS_Y_AXIS
#define Y_APPLY_DIR(v,Q) Y_DIR_WRITE(v)
#define Y_APPLY_STEP(v,Q) Y_STEP_WRITE(v)
#define Y_APPLY_DIR(FWD,Q) Y_DIR_WRITE(FWD)
#define Y_APPLY_STEP(FWD,Q) Y_STEP_WRITE(FWD)
#endif
#if NUM_Z_STEPPERS == 4
#define Z_APPLY_DIR(v,Q) do{ \
Z_DIR_WRITE(v); Z2_DIR_WRITE(INVERT_DIR(Z2_VS_Z, v)); \
Z3_DIR_WRITE(INVERT_DIR(Z3_VS_Z, v)); Z4_DIR_WRITE(INVERT_DIR(Z4_VS_Z, v)); \
#define Z_APPLY_DIR(FWD,Q) do{ \
Z_DIR_WRITE(FWD); Z2_DIR_WRITE(INVERT_DIR(Z2_VS_Z, FWD)); \
Z3_DIR_WRITE(INVERT_DIR(Z3_VS_Z, FWD)); Z4_DIR_WRITE(INVERT_DIR(Z4_VS_Z, FWD)); \
}while(0)
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z_APPLY_STEP(v,Q) QUAD_ENDSTOP_APPLY_STEP(Z,v)
#define Z_APPLY_STEP(FWD,Q) QUAD_ENDSTOP_APPLY_STEP(Z,FWD)
#elif ENABLED(Z_STEPPER_AUTO_ALIGN)
#define Z_APPLY_STEP(v,Q) QUAD_SEPARATE_APPLY_STEP(Z,v)
#define Z_APPLY_STEP(FWD,Q) QUAD_SEPARATE_APPLY_STEP(Z,FWD)
#else
#define Z_APPLY_STEP(v,Q) do{ Z_STEP_WRITE(v); Z2_STEP_WRITE(v); Z3_STEP_WRITE(v); Z4_STEP_WRITE(v); }while(0)
#define Z_APPLY_STEP(FWD,Q) do{ Z_STEP_WRITE(FWD); Z2_STEP_WRITE(FWD); Z3_STEP_WRITE(FWD); Z4_STEP_WRITE(FWD); }while(0)
#endif
#elif NUM_Z_STEPPERS == 3
#define Z_APPLY_DIR(v,Q) do{ \
Z_DIR_WRITE(v); Z2_DIR_WRITE(INVERT_DIR(Z2_VS_Z, v)); Z3_DIR_WRITE(INVERT_DIR(Z3_VS_Z, v)); \
#define Z_APPLY_DIR(FWD,Q) do{ \
Z_DIR_WRITE(FWD); Z2_DIR_WRITE(INVERT_DIR(Z2_VS_Z, FWD)); Z3_DIR_WRITE(INVERT_DIR(Z3_VS_Z, FWD)); \
}while(0)
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z_APPLY_STEP(v,Q) TRIPLE_ENDSTOP_APPLY_STEP(Z,v)
#define Z_APPLY_STEP(FWD,Q) TRIPLE_ENDSTOP_APPLY_STEP(Z,FWD)
#elif ENABLED(Z_STEPPER_AUTO_ALIGN)
#define Z_APPLY_STEP(v,Q) TRIPLE_SEPARATE_APPLY_STEP(Z,v)
#define Z_APPLY_STEP(FWD,Q) TRIPLE_SEPARATE_APPLY_STEP(Z,FWD)
#else
#define Z_APPLY_STEP(v,Q) do{ Z_STEP_WRITE(v); Z2_STEP_WRITE(v); Z3_STEP_WRITE(v); }while(0)
#define Z_APPLY_STEP(FWD,Q) do{ Z_STEP_WRITE(FWD); Z2_STEP_WRITE(FWD); Z3_STEP_WRITE(FWD); }while(0)
#endif
#elif NUM_Z_STEPPERS == 2
#define Z_APPLY_DIR(v,Q) do{ Z_DIR_WRITE(v); Z2_DIR_WRITE(INVERT_DIR(Z2_VS_Z, v)); }while(0)
#define Z_APPLY_DIR(FWD,Q) do{ Z_DIR_WRITE(FWD); Z2_DIR_WRITE(INVERT_DIR(Z2_VS_Z, FWD)); }while(0)
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Z,v)
#define Z_APPLY_STEP(FWD,Q) DUAL_ENDSTOP_APPLY_STEP(Z,FWD)
#elif ENABLED(Z_STEPPER_AUTO_ALIGN)
#define Z_APPLY_STEP(v,Q) DUAL_SEPARATE_APPLY_STEP(Z,v)
#define Z_APPLY_STEP(FWD,Q) DUAL_SEPARATE_APPLY_STEP(Z,FWD)
#else
#define Z_APPLY_STEP(v,Q) do{ Z_STEP_WRITE(v); Z2_STEP_WRITE(v); }while(0)
#define Z_APPLY_STEP(FWD,Q) do{ Z_STEP_WRITE(FWD); Z2_STEP_WRITE(FWD); }while(0)
#endif
#elif HAS_Z_AXIS
#define Z_APPLY_DIR(v,Q) Z_DIR_WRITE(v)
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v)
#define Z_APPLY_DIR(FWD,Q) Z_DIR_WRITE(FWD)
#define Z_APPLY_STEP(FWD,Q) Z_STEP_WRITE(FWD)
#endif
#if HAS_I_AXIS
#define I_APPLY_DIR(v,Q) I_DIR_WRITE(v)
#define I_APPLY_STEP(v,Q) I_STEP_WRITE(v)
#define I_APPLY_DIR(FWD,Q) I_DIR_WRITE(FWD)
#define I_APPLY_STEP(FWD,Q) I_STEP_WRITE(FWD)
#endif
#if HAS_J_AXIS
#define J_APPLY_DIR(v,Q) J_DIR_WRITE(v)
#define J_APPLY_STEP(v,Q) J_STEP_WRITE(v)
#define J_APPLY_DIR(FWD,Q) J_DIR_WRITE(FWD)
#define J_APPLY_STEP(FWD,Q) J_STEP_WRITE(FWD)
#endif
#if HAS_K_AXIS
#define K_APPLY_DIR(v,Q) K_DIR_WRITE(v)
#define K_APPLY_STEP(v,Q) K_STEP_WRITE(v)
#define K_APPLY_DIR(FWD,Q) K_DIR_WRITE(FWD)
#define K_APPLY_STEP(FWD,Q) K_STEP_WRITE(FWD)
#endif
#if HAS_U_AXIS
#define U_APPLY_DIR(v,Q) U_DIR_WRITE(v)
#define U_APPLY_STEP(v,Q) U_STEP_WRITE(v)
#define U_APPLY_DIR(FWD,Q) U_DIR_WRITE(FWD)
#define U_APPLY_STEP(FWD,Q) U_STEP_WRITE(FWD)
#endif
#if HAS_V_AXIS
#define V_APPLY_DIR(v,Q) V_DIR_WRITE(v)
#define V_APPLY_STEP(v,Q) V_STEP_WRITE(v)
#define V_APPLY_DIR(FWD,Q) V_DIR_WRITE(FWD)
#define V_APPLY_STEP(FWD,Q) V_STEP_WRITE(FWD)
#endif
#if HAS_W_AXIS
#define W_APPLY_DIR(v,Q) W_DIR_WRITE(v)
#define W_APPLY_STEP(v,Q) W_STEP_WRITE(v)
#define W_APPLY_DIR(FWD,Q) W_DIR_WRITE(FWD)
#define W_APPLY_STEP(FWD,Q) W_STEP_WRITE(FWD)
#endif
#define E0_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(0) : REV_E_DIR(0); }while(0)
#define E1_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(1) : REV_E_DIR(1); }while(0)
#define E2_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(2) : REV_E_DIR(2); }while(0)
#define E3_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(3) : REV_E_DIR(3); }while(0)
#define E4_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(4) : REV_E_DIR(4); }while(0)
#define E5_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(5) : REV_E_DIR(5); }while(0)
#define E6_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(6) : REV_E_DIR(6); }while(0)
#define E7_APPLY_DIR(REV) do{ (REV) ? FWD_E_DIR(7) : REV_E_DIR(7); }while(0)
//#define E0_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(0) : REV_E_DIR(0); }while(0)
//#define E1_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(1) : REV_E_DIR(1); }while(0)
//#define E2_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(2) : REV_E_DIR(2); }while(0)
//#define E3_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(3) : REV_E_DIR(3); }while(0)
//#define E4_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(4) : REV_E_DIR(4); }while(0)
//#define E5_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(5) : REV_E_DIR(5); }while(0)
//#define E6_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(6) : REV_E_DIR(6); }while(0)
//#define E7_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(7) : REV_E_DIR(7); }while(0)
#if DISABLED(MIXING_EXTRUDER)
#define E_APPLY_STEP(v,Q) E_STEP_WRITE(stepper_extruder, v)
#if ENABLED(MIXING_EXTRUDER)
#define E_APPLY_DIR(FWD,Q) do{ if (FWD) { MIXER_STEPPER_LOOP(j) FWD_E_DIR(j); } else { MIXER_STEPPER_LOOP(j) REV_E_DIR(j); } }while(0)
#else
#define E_APPLY_STEP(FWD,Q) E_STEP_WRITE(stepper_extruder, FWD)
#define E_APPLY_DIR(FWD,Q) do{ if (FWD) { FWD_E_DIR(stepper_extruder); } else { REV_E_DIR(stepper_extruder); } }while(0)
#endif
#define CYCLES_TO_NS(CYC) (1000UL * (CYC) / ((F_CPU) / 1000000))
@ -602,16 +605,12 @@ void Stepper::disable_all_steppers() {
}
// Set a single axis direction based on the last set flags.
// A direction bit of "1" indicates reverse or negative motion.
#define SET_STEP_DIR(A) \
if (motor_direction(_AXIS(A))) { \
A##_APPLY_DIR(LOW, false); \
count_direction[_AXIS(A)] = -1; \
} \
else { \
A##_APPLY_DIR(HIGH, false); \
count_direction[_AXIS(A)] = 1; \
}
// A direction bit of "1" indicates forward or positive motion.
#define SET_STEP_DIR(A) do{ \
const bool fwd = motor_direction(_AXIS(A)); \
A##_APPLY_DIR(fwd, false); \
count_direction[_AXIS(A)] = fwd ? 1 : -1; \
}while(0)
/**
* Set the stepper direction of each axis
@ -621,36 +620,15 @@ void Stepper::disable_all_steppers() {
* COREYZ: Y_AXIS=B_AXIS and Z_AXIS=C_AXIS
*/
void Stepper::apply_directions() {
DIR_WAIT_BEFORE();
NUM_AXIS_CODE(
LOGICAL_AXIS_CODE(
SET_STEP_DIR(E),
SET_STEP_DIR(X), SET_STEP_DIR(Y), SET_STEP_DIR(Z), // ABC
SET_STEP_DIR(I), SET_STEP_DIR(J), SET_STEP_DIR(K),
SET_STEP_DIR(U), SET_STEP_DIR(V), SET_STEP_DIR(W)
);
#if HAS_EXTRUDERS
// Because this is valid for the whole block we don't know
// what E steppers will step. Likely all. Set all.
if (motor_direction(E_AXIS)) {
#if ENABLED(MIXING_EXTRUDER)
MIXER_STEPPER_LOOP(j) REV_E_DIR(j);
#else
REV_E_DIR(stepper_extruder);
#endif
count_direction.e = -1;
}
else {
#if ENABLED(MIXING_EXTRUDER)
MIXER_STEPPER_LOOP(j) FWD_E_DIR(j);
#else
FWD_E_DIR(stepper_extruder);
#endif
count_direction.e = 1;
}
#endif // HAS_EXTRUDERS
DIR_WAIT_AFTER();
}
@ -1858,8 +1836,8 @@ void Stepper::pulse_phase_isr() {
#if STEPPER_PAGE_FORMAT == SP_4x4D_128
#define PAGE_SEGMENT_UPDATE(AXIS, VALUE) do{ \
if ((VALUE) < 7) dm[_AXIS(AXIS)] = true; \
else if ((VALUE) > 7) dm[_AXIS(AXIS)] = false; \
if ((VALUE) < 7) dm[_AXIS(AXIS)] = false; \
else if ((VALUE) > 7) dm[_AXIS(AXIS)] = true; \
page_step_state.sd[_AXIS(AXIS)] = VALUE; \
page_step_state.bd[_AXIS(AXIS)] += VALUE; \
}while(0)
@ -1884,8 +1862,7 @@ void Stepper::pulse_phase_isr() {
PAGE_SEGMENT_UPDATE(Z, high >> 4);
PAGE_SEGMENT_UPDATE(E, high & 0xF);
if (dm != last_direction_bits)
set_directions(dm);
if (dm != last_direction_bits) set_directions(dm);
} break;
@ -2409,29 +2386,16 @@ hal_timer_t Stepper::block_phase_isr() {
if (la_active) {
const uint32_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0;
if (la_step_rate != step_rate) {
const bool reverse_e = la_step_rate > step_rate;
la_interval = calc_timer_interval((reverse_e ? la_step_rate - step_rate : step_rate - la_step_rate) >> current_block->la_scaling);
const bool forward_e = la_step_rate < step_rate;
la_interval = calc_timer_interval((forward_e ? step_rate - la_step_rate : la_step_rate - step_rate) >> current_block->la_scaling);
if (reverse_e != motor_direction(E_AXIS)) {
if (forward_e != motor_direction(E_AXIS)) {
last_direction_bits.toggle(E_AXIS);
count_direction.e = -count_direction.e;
DIR_WAIT_BEFORE();
if (reverse_e) {
#if ENABLED(MIXING_EXTRUDER)
MIXER_STEPPER_LOOP(j) REV_E_DIR(j);
#else
REV_E_DIR(stepper_extruder);
#endif
}
else {
#if ENABLED(MIXING_EXTRUDER)
MIXER_STEPPER_LOOP(j) FWD_E_DIR(j);
#else
FWD_E_DIR(stepper_extruder);
#endif
}
E_APPLY_DIR(forward_e, false);
DIR_WAIT_AFTER();
}
@ -2688,13 +2652,13 @@ hal_timer_t Stepper::block_phase_isr() {
#if ENABLED(INPUT_SHAPING_X)
if (shaping_x.enabled) {
const int64_t steps = current_block->direction_bits.x ? -int64_t(current_block->steps.x) : int64_t(current_block->steps.x);
const int64_t steps = current_block->direction_bits.x ? int64_t(current_block->steps.x) : -int64_t(current_block->steps.x);
shaping_x.last_block_end_pos += steps;
// If there are any remaining echos unprocessed, then direction change must
// be delayed and processed in PULSE_PREP_SHAPING. This will cause half a step
// to be missed, which will need recovering and this can be done through shaping_x.remainder.
shaping_x.forward = !current_block->direction_bits.x;
shaping_x.forward = current_block->direction_bits.x;
if (!ShapingQueue::empty_x()) current_block->direction_bits.x = last_direction_bits.x;
}
#endif
@ -2702,9 +2666,9 @@ hal_timer_t Stepper::block_phase_isr() {
// Y follows the same logic as X (but the comments aren't repeated)
#if ENABLED(INPUT_SHAPING_Y)
if (shaping_y.enabled) {
const int64_t steps = current_block->direction_bits.y ? -int64_t(current_block->steps.y) : int64_t(current_block->steps.y);
const int64_t steps = current_block->direction_bits.y ? int64_t(current_block->steps.y) : -int64_t(current_block->steps.y);
shaping_y.last_block_end_pos += steps;
shaping_y.forward = !current_block->direction_bits.y;
shaping_y.forward = current_block->direction_bits.y;
if (!ShapingQueue::empty_y()) current_block->direction_bits.y = last_direction_bits.y;
}
#endif
@ -3450,36 +3414,36 @@ void Stepper::report_positions() {
#if HAS_Z_AXIS
// Z is handled differently to update the stepper
// counts (needed by Marlin for bed level probing).
const bool z_dir = TEST(command, FT_BIT_DIR_Z),
const bool z_fwd = TEST(command, FT_BIT_DIR_Z),
z_step = TEST(command, FT_BIT_STEP_Z);
#endif
if (applyDir) {
TERN_(HAS_X_AXIS, X_DIR_WRITE(TEST(command, FT_BIT_DIR_X)));
TERN_(HAS_Y_AXIS, Y_DIR_WRITE(TEST(command, FT_BIT_DIR_Y)));
TERN_(HAS_Z_AXIS, Z_DIR_WRITE(z_dir));
TERN_(HAS_EXTRUDERS, E0_DIR_WRITE(TEST(command, FT_BIT_DIR_E)));
TERN_(HAS_X_AXIS, X_APPLY_DIR(TEST(command, FT_BIT_DIR_X), false));
TERN_(HAS_Y_AXIS, Y_APPLY_DIR(TEST(command, FT_BIT_DIR_Y), false));
TERN_(HAS_Z_AXIS, Z_APPLY_DIR(z_fwd, false));
TERN_(HAS_EXTRUDERS, E_APPLY_DIR(TEST(command, FT_BIT_DIR_E), false));
DIR_WAIT_AFTER();
}
TERN_(HAS_X_AXIS, X_STEP_WRITE(TEST(command, FT_BIT_STEP_X)));
TERN_(HAS_Y_AXIS, Y_STEP_WRITE(TEST(command, FT_BIT_STEP_Y)));
TERN_(HAS_Z_AXIS, Z_STEP_WRITE(z_step));
TERN_(HAS_EXTRUDERS, E0_STEP_WRITE(TEST(command, FT_BIT_STEP_E)));
TERN_(HAS_X_AXIS, X_APPLY_STEP(TEST(command, FT_BIT_STEP_X), false));
TERN_(HAS_Y_AXIS, Y_APPLY_STEP(TEST(command, FT_BIT_STEP_Y), false));
TERN_(HAS_Z_AXIS, Z_APPLY_STEP(z_step, false));
TERN_(HAS_EXTRUDERS, E_APPLY_STEP(TEST(command, FT_BIT_STEP_E), false));
START_TIMED_PULSE();
#if HAS_Z_AXIS
// Update step counts
if (z_step) count_position.z += z_dir ? 1 : -1;
if (z_step) count_position.z += z_fwd ? 1 : -1;
#endif
AWAIT_HIGH_PULSE();
X_STEP_WRITE(0);
TERN_(HAS_Y_AXIS, Y_STEP_WRITE(0));
TERN_(HAS_Z_AXIS, Z_STEP_WRITE(0));
TERN_(HAS_EXTRUDERS, E0_STEP_WRITE(0));
TERN_(HAS_X_AXIS, X_APPLY_STEP(0, false));
TERN_(HAS_Y_AXIS, Y_APPLY_STEP(0, false));
TERN_(HAS_Z_AXIS, Z_APPLY_STEP(0, false));
TERN_(HAS_EXTRUDERS, E_APPLY_STEP(0, false));
} // Stepper::fxdTiCtrl_stepper
@ -3565,7 +3529,7 @@ void Stepper::report_positions() {
#define _ENABLE_AXIS(A) enable_axis(_AXIS(A))
#define _READ_DIR(AXIS) AXIS ##_DIR_READ()
#define _APPLY_DIR(AXIS, INVERT) AXIS ##_APPLY_DIR(INVERT, true)
#define _APPLY_DIR(AXIS, FWD) AXIS ##_APPLY_DIR(FWD, true)
#if MINIMUM_STEPPER_PULSE
#define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE) * CYCLES_PER_MICROSECOND)

View file

@ -524,7 +524,7 @@ class Stepper {
// Quickly stop all steppers
FORCE_INLINE static void quick_stop() { abort_current_block = true; }
// The direction of a single motor. A true result indicates reversed or negative motion.
// The direction of a single motor. A true result indicates forward or positive motion.
FORCE_INLINE static bool motor_direction(const AxisEnum axis) { return last_direction_bits[axis]; }
// The last movement direction was not null on the specified axis. Note that motor direction is not necessarily the same.