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

Conversation

vedransi
Copy link

Description

This Pull Request is for the implementation of the Differential Extruder, currently only for RepRap printers such as Creality Ender 3 v2.
Differential extruder works by adding X movement to the E movement, and then sends the sum to the E stepper. E stepper drives a loop timing belt that engages a timing pulley on the print head. This timing pulley is attached to the extrusion wheel. The end result is that the extrusion happens only when there's a difference between X stepper rotation and E stepper rotation.
For example, when gcode instructs the printer to move X 10mm to the left, both X stepper and E stepper rotate and move their corresponding belts 10mm to the left. That is, X stepper moves the print head 10mm to the left and the E stepper moves the loop timing belt 10mm to the left. Since there's no difference between these two belts, the timing pulley on the print head does not rotate and no extrusion happens.
When gcode instructs the printer to move 10mm to the left and to extrude 3mm of filament, X stepper will rotate and move the print head 10mm to the left, but E stepper will rotate more and will move the loop belt 13mm. The timing pulley on the print head will pick up the difference of 3mm, rotate the extrusion wheel and extrude the filament.
You can find the video of the differential extruder in action here:
https://youtu.be/tZTGylyoT1I
And here are the photos of my Creality Ender 3 v2 with a differential extruder:

Photo_1

Photo_2

Photo_3

Photo_4

Requirements

This extruder requires two additional mounts and a print head block, all of which are easy to print. In its current incarnation, it also requires a 760mm loop timing belt, two additional timing pulleys, two small smooth idlers, one toothed idler and a tensioner for the loop timing belt, plus a number of small nuts, bolts and washers.

DiffEx.zip

Since it is also important for the print head to slide accurately along the X axis, it is recommended to install a sliding rail / block assembly on the X axis gantry. For example, the standard print head of the Creality Ender 3 v2 which has three wheels had too much play in the system, which made it twist clockwise and anticlockwise according to the movements of the loop timing belt. A sliding rail with a block eliminated the twist and fixed the problem.

Benefits

Differential extruder combines the benefits of the Bowden extruder (lightweight print head, faster printing) with the benefits of the Direct Drive extruder (precise filament handling, flexible filaments, abrasive filaments). I've been printing with it for a while now and it handles PETG, PETG+CF, TPU and PolyCast with no problems at all.

Configurations

I developed this extruder by using Creality Ender 3 v2 printer. If you want to test it on the same model, attached is the zip file with STLs for mounts, the tensioner and the print head. The print head is mounted on a slide rail assembly that is available on eBay and has a red aluminum L-profile for the print head mount. Please examine the photos attached above.

@thinkyhead @ellensp @thisiskeithb Could you please review this pull request?
Feasibility tests for Differential Extruder are in Configuration.h and they basically check if there's only 1 extruder and whether the motherboard is "BOARD_CREALITY_V4". I'm not entirely happy with this second test. Is there a way to just test if the board is 32-bit?

Also for your consideration is the fact that changes in planner.cpp make it handle the differential extruder when a print job is active, whilst the changes in stepper.cpp only handle the differential extruder when a print job is NOT active, i.e. when you issue commands via the printer's console/screen/click-wheel.
If you think that changes could be made to one cpp file only that could handle both cases ("print job active" and "print job not active"), please advise. I tried a few options already and the current solution seems to work best.

Thanks heaps in advance for helping.
Cheers
Vedran

Related Issues

Added two code blocks for Differential extruder
Added the Differential Extruder block
Added the fourth and fifth code blocks for Differential Extruder
@thisiskeithb
Copy link
Member

What happened with #27558 ?

@thinkyhead @ellensp @thisiskeithb Could you please review this pull request?

Someone (most likely thinkyhead) will review this PR when they get a chance and clean things up. There’s no need to tag us directly.

@thisiskeithb thisiskeithb linked an issue Dec 12, 2024 that may be closed by this pull request
@vedransi
Copy link
Author

Hi Keith,
I'm not sure what happened with the old PR, but it could have disappeared when I discarded all its commits because I was getting error messages that there was a conflict with the main branch. Apologies if I made an unnecessary duplication, but at least this PR only has 3 commits instead of 40.
Thanks
V

// 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.

if (print_job_timer.isRunning()) {
// Calculate the differential steps for the extruder
const int32_t e_steps = lround(machine.e * steps_per_mm[E_AXIS])
+ lround(machine.x * steps_per_mm[X_AXIS]);
Copy link
Member

Choose a reason for hiding this comment

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

We provide steps_per_mm specifically to avoid division in converting mm to steps.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks. That looks better. FYI, I edited most of the code with a lot of help from CoPilot. C++ novice...

Copy link
Author

Choose a reason for hiding this comment

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

I was getting an error that steps_per_mm was not defined, and Copilot's suggestion was to use settings.axis_steps_per_mm instead. The end result for the statement in lines 3066 and 3067 was:

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]);

The test print came out good

#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.

@thinkyhead thinkyhead added this to the After 2.1.3 milestone Dec 12, 2024
I was getting a "red wavy underline" warning that steps_per_mm variable was not defined. Edited the name of the variable as per Copilot's suggestion. Compiled, uploaded, printer prints ok, so it's probably all good.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FR] Remote extruder kinematics
3 participants