Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Differential Extruder #27582

Open
wants to merge 7 commits into
base: bugfix-2.1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@
// :[0, 1, 2, 3, 4, 5, 6, 7, 8]
#define EXTRUDERS 1

/**
* Differential Extruder
* Currently works only for single-extruder RepRap 32-bit.
*/
//#define DIFFERENTIAL_EXTRUDER

// Generally expected filament diameter (1.75, 2.85, 3.0, ...). Used for Volumetric, Filament Width Sensor, etc.
#define DEFAULT_NOMINAL_FILAMENT_DIA 1.75

Expand Down
5 changes: 5 additions & 0 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -4503,6 +4503,11 @@ static_assert(WITHIN(MULTISTEPPING_LIMIT, 1, 128) && IS_POWER_OF_2(MULTISTEPPING
#error "Only enable ULTIPANEL_FEEDMULTIPLY or ULTIPANEL_FLOWPERCENT, but not both."
#endif

// Differential Extruder requires the magic of Creality V4
#if ENABLED(DIFFERENTIAL_EXTRUDER) && !(EXTRUDERS == 1 && MB(CREALITY_V4))
#error "DIFFERENTIAL_EXTRUDER requires MOTHERBOARD BOARD_CREALITY_V4 and EXTRUDERS 1."
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks to me like the feature could work with any board, including AVR, as there are no complex calculations.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally thought the same, but I was getting a deluge of errors from automatic tests, many of them in regards to 8-bit Arduino. Some of the errors referred to non-defined Cartesian axis variables, so I thought I'd better limit the scope of my extruder to RepRap kinematics, but I couldn't find a test for RepRap. That's the only reason why I test for Creality V4, so please feel free to suggest a more universal test that will just check if the kinematics is RepRap.


// Misc. Cleanup
#undef _TEST_PWM
#undef _NUM_AXES_STR
Expand Down
17 changes: 17 additions & 0 deletions Marlin/src/module/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@

#include "../MarlinCore.h"

#if ENABLED(DIFFERENTIAL_EXTRUDER)
#include "printcounter.h"
#endif

#if HAS_LEVELING
#include "../feature/bedlevel/bedlevel.h"
#endif
Expand Down Expand Up @@ -3053,6 +3057,19 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s

#else // !IS_KINEMATIC

// Differential Extruder
// The sum of X and E movement is applied to the E stepper.
// Outside of a print job, the differential extruder is handled by stepper.cpp.
#if ENABLED(DIFFERENTIAL_EXTRUDER)
if (print_job_timer.isRunning()) {
// Calculate the differential steps for the extruder
const int32_t e_steps = lround(machine.e * settings.axis_steps_per_mm[E_AXIS])
+ lround(machine.x * settings.axis_steps_per_mm[X_AXIS]);
// Update the machine position with the differential steps
machine.e = e_steps * mm_per_step[E_AXIS];
}
#endif

return buffer_segment(machine, fr_mm_s, extruder, hints);

#endif
Expand Down
25 changes: 23 additions & 2 deletions Marlin/src/module/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ Stepper stepper; // Singleton
#include "planner.h"
#include "motion.h"

#if ENABLED(DIFFERENTIAL_EXTRUDER)
#include "printcounter.h"
#endif

#if ENABLED(FT_MOTION)
#include "ft_motion.h"
#endif
Expand Down Expand Up @@ -1783,6 +1787,10 @@ void Stepper::pulse_phase_isr() {
// Direct Stepping page?
const bool is_page = current_block->is_page();

#if ENABLED(DIFFERENTIAL_EXTRUDER)
const bool is_print_job = print_job_timer.isRunning();
#endif

do {
AxisFlags step_needed{0};

Expand Down Expand Up @@ -1845,18 +1853,31 @@ void Stepper::pulse_phase_isr() {
DELTA_ERROR = de; \
}while(0)

// Differential Extruder moves E along with X
#if ENABLED(DIFFERENTIAL_EXTRUDER)
#define DIFFERENTIAL_E_PULSE(AXIS, ONSTEP) \
if (!is_print_job && _AXIS(AXIS) == X_AXIS) { \
E_APPLY_DIR(count_direction[X_AXIS] > 0, false); /* Match E direction to X */ \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible this DIR change will not be registered before the STEP is applied on the following line. Any direction change should include a delay so the driver can register the change before the next step signal. The stepper ISR currently aims to set all stepper DIR signals first, then delay, and then do all the steps. This way we only need one delay for all stepper DIRs. Any added delays will cause a reduction in the top stepping rate. But, we do need to add some kind of delay right here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I'll take a look at the code you changed in stepper.cpp and test it on my printer.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Homing and other commands issued via console/screen/click-wheel work ok.
Prints also come out ok, but that's up to planner.cpp

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue for which I do have a solution, but it could be more elegant. Here it is:
At the beginning of a gcode file, there is a G28 command ("home all axes"). When this command is actioned, I think the job timer is on, but for some reason planner.cpp does not get involved in calculating the pulses for steppers. G28 appears to go directly to stepper.cpp, which then processes it with no regard to Differential Extruder. The end result is that X and E steppers get out of sync and lots of skipping happens on the loop belt.
If I put an M76 command before G28, and then an M77 command after it, everything works fine.

E_APPLY_STEP(ONSTEP ? _STEP_STATE(E) : !_STEP_STATE(E), false); /* Add the pulse to the E stepper */ \
}
#else
#define DIFFERENTIAL_E_PULSE(...) NOOP
#endif

// Start an active pulse if needed
#define PULSE_START(AXIS) do{ \
if (step_needed.test(_AXIS(AXIS))) { \
count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \
_APPLY_STEP(AXIS, _STEP_STATE(AXIS), 0); \
_APPLY_STEP(AXIS, _STEP_STATE(AXIS), false); \
DIFFERENTIAL_E_PULSE(AXIS, true); \
} \
}while(0)

// Stop an active pulse if needed
#define PULSE_STOP(AXIS) do { \
if (step_needed.test(_AXIS(AXIS))) { \
_APPLY_STEP(AXIS, !_STEP_STATE(AXIS), 0); \
_APPLY_STEP(AXIS, !_STEP_STATE(AXIS), false); \
DIFFERENTIAL_E_PULSE(AXIS, false); \
} \
}while(0)

Expand Down