DIFFERENTIAL_EXTRUDER (#28023)

This commit is contained in:
Vedran 2025-11-17 05:22:03 +11:00 committed by GitHub
parent ef8873d6ef
commit 98c72a3b65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 93 additions and 4 deletions

View file

@ -305,6 +305,18 @@
#endif
/**
* Differential Extruder
*
* The X and E steppers work together to create a differential drive system.
* Simple : E steps = X + E ; X steps = X (E drives a loop, X stays the same)
* Balanced: E steps = X + E/2 ; X steps = X - E/2 (Dual loop system)
*/
//#define DIFFERENTIAL_EXTRUDER
#if ENABLED(DIFFERENTIAL_EXTRUDER)
//#define BALANCED_DIFFERENTIAL_EXTRUDER
#endif
/**
* Switching Toolhead
*

View file

@ -934,6 +934,19 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#endif
#endif
/**
* Differential Extruder requirements
*/
#if ENABLED(DIFFERENTIAL_EXTRUDER)
#if EXTRUDERS != 1
#error "DIFFERENTIAL EXTRUDER currently requires a single extruder (EXTRUDERS = 1)."
#elif !IS_FULL_CARTESIAN
#error "DIFFERENTIAL EXTRUDER requires standard Cartesian kinematics."
#elif !defined(CPU_32_BIT)
#error "DIFFERENTIAL EXTRUDER requires a 32-bit CPU."
#endif
#endif
/**
* Generic Switching Toolhead requirements
*/

View file

@ -33,7 +33,7 @@ ftm_resonance_test_params_t ResonanceGenerator::rt_params; // Resonance test
bool ResonanceGenerator::active = false; // Resonance test active
bool ResonanceGenerator::done = false; // Resonance test done
float ResonanceGenerator::rt_time = FTM_TS; // Resonance test timer
float ResonanceGenerator::rt_time = FTM_TS; // Resonance test timer
float ResonanceGenerator::timeline = 0.0f;
ResonanceGenerator::ResonanceGenerator() {}

View file

@ -2725,6 +2725,70 @@ hal_timer_t Stepper::block_phase_isr() {
// Based on the oversampling factor, do the calculations
step_event_count = current_block->step_event_count << oversampling_factor;
#if ENABLED(DIFFERENTIAL_EXTRUDER)
// X and E work together as a differential mechanism:
// When X and E move in the same direction they move the print carriage,
// and when X and E move in opposite directions they cause extrusion.
// NOTE: All calculations performed per block, preserving Bresenham timing coordination
if (current_block->steps.x > 0 || current_block->steps.e > 0) {
// Calculate signed step counts based on directions
const int32_t x_signed_steps = current_block->direction_bits.x ? current_block->steps.x : -int32_t(current_block->steps.x),
e_signed_steps = current_block->direction_bits.e ? current_block->steps.e : -int32_t(current_block->steps.e);
#if ENABLED(BALANCED_DIFFERENTIAL_EXTRUDER)
// BALANCED DIFFERENTIAL EXTRUDER: X stepper drives one loop belt
// and E stepper drives another loop belt. Two belts mesh at the extruder
// X stepper: X - E/2 (carriage movement - half extrusion)
// E stepper: X + E/2 (carriage movement + half extrusion)
// Net extrusion: (X + E/2) - (X - E/2) = E
// (This will work great once I figure out what to do when E/2 is not integer!)
// Split extrusion 50/50 between X and E steppers
const int32_t half_e_steps = e_signed_steps / 2;
// X stepper: X movement - half E extrusion
const int32_t new_x_steps = x_signed_steps - half_e_steps;
current_block->steps.x = ABS(new_x_steps);
// Update X axis direction
current_block->direction_bits.x = new_x_steps >= 0;
// E stepper: X movement + half E extrusion
const int32_t new_e_steps = x_signed_steps + half_e_steps;
current_block->steps.e = ABS(new_e_steps);
// Update E axis direction
current_block->direction_bits.e = new_e_steps >= 0;
#else // !BALANCED_DIFFERENTIAL_EXTRUDER
// SIMPLE SINGLE-LOOP DIFFERENTIAL EXTRUDER: X stepper drives the carriage as usual,
// while E stepper drives a loop belt that's meshed around the extruder.
// X stepper: X only (carriage movement)
// E stepper: X + E (carriage movement + extrusion)
// Net extrusion: (X + E) - X = E
// Calculate net E steps (X movement + extrusion)
const int32_t net_e_steps = x_signed_steps + e_signed_steps;
// Update the block with new E step count
current_block->steps.e = ABS(net_e_steps);
// Update direction bit for E axis
current_block->direction_bits.e = net_e_steps >= 0;
#endif // !BALANCED_DIFFERENTIAL_EXTRUDER
// NOTE: DO NOT modify the step_event_count! This would change XYZ timing!
// Bresenham distributes X and E steps over the time base.
}
#endif // DIFFERENTIAL_EXTRUDER
// Initialize Bresenham delta errors to 1/2
delta_error = -int32_t(step_event_count);
TERN_(HAS_ROUGH_LIN_ADVANCE, la_delta_error = delta_error);
@ -3322,7 +3386,7 @@ void Stepper::init() {
}
void Stepper::set_shaping_frequency(const AxisEnum axis, const float freq) {
// Enabling or disabling shaping whilst moving can result in lost steps
// Enabling or disabling shaping while moving can result in lost steps
planner.synchronize();
const bool was_on = hal.isr_state();

View file

@ -13,5 +13,5 @@ restore_configs
opt_set MOTHERBOARD BOARD_BTT_SKR_E3_DIP \
SERIAL_PORT 1 SERIAL_PORT_2 -1 \
X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2130
opt_enable SERIAL_DMA ULTI_CONTROLLER
exec_test $1 $2 "BTT SKR E3 DIP 1.0 | Mixed TMC Drivers" "$3"
opt_enable SERIAL_DMA ULTI_CONTROLLER DIFFERENTIAL_EXTRUDER BALANCED_DIFFERENTIAL_EXTRUDER
exec_test $1 $2 "BTT SKR E3 DIP 1.0 | Mixed TMC Drivers | Differential Extruder" "$3"