Skip to content

extruder: Add mixing extruder (with example usage in a printer.cfg)#3920

Closed
konsumverweigerer wants to merge 12 commits into
Klipper3d:masterfrom
konsumverweigerer:feature/mixingextruder
Closed

extruder: Add mixing extruder (with example usage in a printer.cfg)#3920
konsumverweigerer wants to merge 12 commits into
Klipper3d:masterfrom
konsumverweigerer:feature/mixingextruder

Conversation

@konsumverweigerer

@konsumverweigerer konsumverweigerer commented Feb 12, 2021

Copy link
Copy Markdown
Contributor

Supported G-codes are:

M163 Sx Pa.a:b.b:..:h.h, M164 Sx
- set ratios for virtual mixing extruders
M567 Px Ea.a:b.b:..:h.h
- set mixing for virtual mixing extruders
G1 Ea.a:b.b:..:h.h
- extrude with mixing (allowed when mixingextruder is active)

ACTIVATE_EXTRUDER EXTRUDER=mixingextruder
MIXING_STATUS EXTRUDER=mixingextruder

Signed-off-by: Peter Gruber gruberp@googlemail.com

Supported G-codes are:

M163 Sx Pa:b:..:h, M164 Sx
     - set ratios for virtual mixing extruders
M567 Px Ea:b:..:h
     - set mixing for virtual mixing extruders
G1 Ea:b:..:h
     - extrude with mixing (allowed when mixingextruder is active)

ACTIVATE_EXTRUDER EXTRUDER=mixingextruder<x>
MIXING_STATUS EXTRUDER=mixingextruder<x>


Signed-off-by: Peter Gruber <gruberp@googlemail.com>
Signed-off-by: Peter Gruber <gruberp@googlemail.com>
@ETE-Design

ETE-Design commented Feb 12, 2021

Copy link
Copy Markdown

Mabye you should also add some info to the Config_Reference.md

Signed-off-by: Peter Gruber <gruberp@googlemail.com>
Initial documentation for the mixingextruder section. Also documents
the available additional g-codes.

Signed-off-by: Peter Gruber <gruberp@googlemail.com>
@ETE-Design

ETE-Design commented Feb 14, 2021

Copy link
Copy Markdown

@konsumverweigerer Will Marlin - M165 + M166 also work with this PR, or is it just made from RepRap G-Code? Just to know what method to use for Slicers... Whan Silcer do you use to test?

@konsumverweigerer

konsumverweigerer commented Feb 15, 2021 via email

Copy link
Copy Markdown
Contributor Author

Signed-off-by: Peter Gruber <gruberp@googlemail.com>
Signed-off-by: Peter Gruber <gruberp@googlemail.com>
@KevinOConnor

Copy link
Copy Markdown
Collaborator

Interesting. My high-level feedback, though, is that I think we'd need to find a way to implement mixing extruders without "arcane g-code syntax" in order to merge into the main Klipper repository. I'm reluctant to introduce a new syntax for G1, and I'm reluctant to implement an M165 command with arbitrary A/B/C/D/H/I parameters.

FWIW, my preference would be to come up with some scheme with commands such as SET_MIXING_EXTRUDER EXTRUDER=extruder MIXING_MOTOR=my_motor1 SCALE=0.25.

Cheers,
-Kevin

@rbarreiros

rbarreiros commented Feb 22, 2021

Copy link
Copy Markdown

I'm actually looking at this, since I'm planning on building my corexy with a dual mixing hotend, and was investigating klipper support with virtual toolheads to create mixing colors, was searching klippy code for something like this untill I stumbled on this PR.

@KevinOConnor I don't know the 'official' cura gcode command set for this specific functionality, but, you mean like creating an custom klipper gcode command like you suggested and then plug the 'official' ones used by cura ? (like M163, M164, etc) ?

P.S. I don't think M165 is used by cura...

@konsumverweigerer

konsumverweigerer commented Feb 23, 2021

Copy link
Copy Markdown
Contributor Author

I used resources like

as an definition for the g-codes. The G1 extension seems to be reprap specific, it is mentioned in some places in the reprap g-code wiki but never actually strictly defined. I simply found it easy to implement and very useful ...

@KevinOConnor I guess most of the functionality could also be implemented with a SET_MIXING_EXTRUDER (or simliar) commands and then if someone wants/needs the marlin/reprap g-code can implement them as g-code macros. I guess the G1 extension would not be possible this way. Also I would prefer to the set the ratio/scale for all motors/extruders at once, that makes sanity checks much easier:

  • controlling combined extrusion: in the simplest case make sure that the scales add up to one
  • avoid some extruders doing negative extrusion while others do positive effectively pushing material back up tube)

What do yoou think of such an approach?

@KevinOConnor

Copy link
Copy Markdown
Collaborator

FWIW, sounds fine to me. It may help if you could mock up an example config section and an example set of commands.

-Kevin

@ETE-Design

Copy link
Copy Markdown

@konsumverweigerer Haven't tryed Mixing at all yet, but is there a way to change color / mix without the need of making virtual mixing extruders, so you don't have to define 100 virtual extruders? And if there is then how to set it up in Prusa Slicer / Cura?

Signed-off-by: Peter Gruber <gruberp@googlemail.com>
Add some basic g-code to control mixing and gradients. These commands
have comprehensive names and can be used to implement all flavors
(marlin, reprap) of the standard mixing g-codes M163-M166, M567 via
g-code macros. Samples for that are provided.


Signed-off-by: Peter Gruber <gruberp@googlemail.com>
@konsumverweigerer

Copy link
Copy Markdown
Contributor Author

@KevinOConnor I have reworked the commands so that taht e few comprehesive ones are enough to control the mixing and added example g-code macros which implement the marlin/reprap specific M163, ... M567.

@konsumverweigerer

Copy link
Copy Markdown
Contributor Author

@ETE-Design The easiest way would be to add something like this to your start g-codes in your slicer after you have added the [mixingextruder] section to your printer.cfg (assuming you have a 2in-1out mixing nozzle):

ACTIVATE_EXTRUDER EXTRUDER=mixingextruder
SET_MIXING_EXTRUDER EXTRUDER=mixingextruder MIXING_MOTOR=0 SCALE=50
SET_MIXING_EXTRUDER EXTRUDER=mixingextruder MIXING_MOTOR=1 SCALE=50
SAVE_MIXING_EXTRUDERS EXTRUDER=mixingextruder

This would activate a 50%/50% mixing.

You could also add something like this to your printer.cfg:

[gcode_macro T0]
gcode:
  ACTIVATE_EXTRUDER extruder=extruder

[gcode_macro T1]
gcode:
  ACTIVATE_EXTRUDER extruder=extruder1

[gcode_macro T2]
gcode:
  ACTIVATE_EXTRUDER EXTRUDER=mixingextruder
  SET_MIXING_EXTRUDER EXTRUDER=mixingextruder MIXING_MOTOR=0 SCALE=50
  SET_MIXING_EXTRUDER EXTRUDER=mixingextruder MIXING_MOTOR=1 SCALE=50
  SAVE_MIXING_EXTRUDERS EXTRUDER=mixingextruder

Then you would have 3 Tools available: The first 2 solely first and the second extruder respectively and the 3. a 50%/50% mixing. Then you could use these tool directly in your slicer (details vary between slicers).

@ETE-Design

Copy link
Copy Markdown

@konsumverweigerer So if you want to have 100 nuances for colors you have to make 100 Tool's? Seems like there is not an easy way if you want a lot of nuances :-(

@konsumverweigerer

Copy link
Copy Markdown
Contributor Author

@ETE-Design Which slicer does support those 100 nuances? If the slicer support it you can can use the SET/SAVE_MIXING directly in the g-code (without using tools at all). You could even change the mix before each G1.

Alternatively you could look into the the ADD_MIXING_GRADIENT command. Currently I have implemented a linear gradient based on the Z coordinate (height) but I would be easy to add other schemes.

@KevinOConnor

Copy link
Copy Markdown
Collaborator

Interesting, thanks.

I'm a little confused on how this all works. At a high-level, an extruder in Klipper is the combination of a heater, a temperature sensor, and an extruder stepper motor. It seems unusual to me that we'd define a mixingextruder as a combination of "extruders". Wouldn't it make more sense for a "mixing extruder" to have a combination of many "extruder_stepper"? Perhaps we should consider expanding extruder_stepper to support the existing SET_E_STEP_DISTANCE command so that it can be used for mixing.

I'm also unsure that fully wrapping all the extruder functionality in new MixingExtruder/MixingMove classes is a good idea. I would think we could use the existing extruder and extruder_stepper functionality and just command it to use different step distances.

On the code side, I did notice the code has a few places where it peeks into member variables of classes in other files - that's something we want to avoid (it's mentioned briefly in docs/Code_Overview.md). It also looks like the code still has some "weird g-code e syntax" - I'd be reluctant to add that to the master Klipper branch.

Separately, I'm also unsure the gradient commands are general purpose enough to add to the main Klipper repository. Perhaps I'm missing something, but they seem like something a slicer could do without needing firmware support. In any case, it's probably best to merge the basic functionality first - then look to add additional features on top of that.

Cheers,
-Kevin

@konsumverweigerer

Copy link
Copy Markdown
Contributor Author

@KevinOConnor I am not sure if pushing the whole mixing stuff down into the steppers is the best idea. The usecase of the "n in-1 out" nozzle simply add some additinal global contraints. If we simply modify the step distance at the steppers we loose the connection to the actual physical conditions a the stepper (eg if we want to reduce the amount of material fed at a stepper by half we would double it step distance so it may trigger limits on aterial/s etc which would also need to bypassed etc). Also I guess we would loose the perspective of how much material is actually going through the nozzle (here we want to have the actual physical limitation checked and stuff like pressure advance still working with total flow going through the nozzle). Also I think conceptually that the step distance is assumed to be constant during a print and might lead to some issues when it changes.

I tried to make the mixing stuff as self contained as possible (keep all changes in the one class which is only loaded when mixing is configured) but if you think a deeper integration into the the extruder/stepper code is more appropriate I can work on a more integrated solution: My idea for that would be to add the nozzle as class and then each extruder would be a combination of a heater, a temperature sensor, an extruder stepper motor and a nozzle and extruders then could share a nozzle like they currently can share a heater. But this route would be a much larger change to the code than the mixingextruder.

I added the gradient stuff since its very convinient and yes z-height based gradients are also easily done in a slicer (eg. very easy in (prusa)sllic3r bit harder in cura). But adding it to klipper opens up the possibility to add non-z-height based gradient (as an example I implemented a gradient based on the distance from the origin) or even fully parametric gradients and those are very hard to implement in the slicer.

I will check the code where it "peeks into member variables" and will try to avoid that.

@KevinOConnor

Copy link
Copy Markdown
Collaborator

I am not sure if pushing the whole mixing stuff down into the steppers is the best idea.

I understand. I'm not sure as well.

I tried to make the mixing stuff as self contained as possible

That make sense. FWIW, my fear is that the Move() and Extruder() classes are too complex to "emulate" from another module. That is, I fear that future changes will be made to those classes and no one will think to update mixingextruder.py.

Unfortunately, I don't really have any good advice. I'd think that we'd want to keep a single extruder trapq instance, but teach the various extruder stepper instances to be able to move a varying amount of distance for the moves on that trapq.

My idea for that would be to add the nozzle as class and then each extruder would be a combination of a heater, a temperature sensor, an extruder stepper motor and a nozzle and extruders then could share a nozzle like they currently can share a heater.

I guess that's possible, but it seems odd to me to "share a nozzle" when that's not really the physical reality. FWIW, it seems to me there's a single "high level extruder", but different stepper motors contributing to it.

-Kevin

Slicers usually produce g-codes to preheat tools/extruders before usage.
This will have undesire effects when multiple extruders share a heater.


Signed-off-by: Peter Gruber <gruberp@googlemail.com>
Also make some small improvements and code cleanups.


Signed-off-by: Peter Gruber <gruberp@googlemail.com>
@konsumverweigerer

Copy link
Copy Markdown
Contributor Author

I did some changes to the mixing code, now the extended G1 command syntax is gone and also the check_move which make the Move/Extruder emulation much simpler. Also I added an adjustment to the extruder class to make the g-codes generated by most slicers compatible without manual changes (no slicer I know does understand the concept of a shared heater).

For a more integrated version my understanding of the physical "extrusion" process would be something like this:
a tool (your high level extruder) forces (the motors/extruders) one or many strands of material through a heated (the heater(s)) nozzle.
Then the motor extruder would control/be controlled by parameters like filament diameter, rotation_distance, stepper, instantaneous_corner_velocity, pressure_advance, etc.
The heater would control/be controlled by parameters like heater*, sensor*, control, pid*.
And the nozzle would control/be controlled by parameters like nozzle_diameter, max_extrude_cross_section, max_extrude_only_velocity,

Then the nozzle could also hold ratios for the motors which feed into it. And the tool would orchestrate it: the toolhead would send moves to the tool (which delegates them to the motors/extruders) and the tool would also handle the temperature commands by sending them to the appropriate heater(s).

Signed-off-by: Peter Gruber <gruberp@googlemail.com>
@KevinOConnor

Copy link
Copy Markdown
Collaborator

FWIW, I think of the "extruder class" more as a "hotend class". It has a nozzle, a heater, a temperature sensor, and one or more "extruder stepper motors" pushing filament to it. It also has a "motion schedule" (ie, trapq) with the list of extrusion amounts that should leave the nozzle along with their timing.

The "shared heater" was, I think in retrospect, a bad choice. Might be worth redoing that with extruder steppers - that is, instead of declaring "two extruders that share a heater" it may be better to declare "one hotend that can have two different stepper motors pushing filament to it".

I think I'm not understanding your proposal (and code) well, because I think I'm not understanding your model.

-Kevin

@konsumverweigerer

Copy link
Copy Markdown
Contributor Author

FWIW, I think of the "extruder class" more as a "hotend class". It has a nozzle, a heater, a temperature sensor, and one or more "extruder stepper motors" pushing filament to it. It also has a "motion schedule" (ie, trapq) with the list of extrusion amounts that should leave the nozzle along with their timing.

So you would see the trapq more at the "hotend" or multiple trapq at the "extruder stepper motors"? In the latgter case the trapq track the ingress filament and the "hotend" needs to also tracks that if the ratios of the stepper motors are changing. In the first case the trapq would track the egress filament at the nozzle and If think each move would have to keep track of the current ratio for the motors. I think both is doable but I would prefer the latter since it would make tracking the state a bit easier.

Maybe "tool" could be an equivalent name for "hotend", or would you see tool more as an abstraction (with hotend as one example): I am thinking about how to implement the M104/M109 commands which reference "tools" which should correspond to the tools in T0, T1 ... commands.

I think I'm not understanding your proposal (and code) well, because I think I'm not understanding your model.

The current code is more of a hack which tries to be as separate as possible and just get the mixing working and get some experience with it. For a better version/integration it would be best to find a common model/wording/label first

@KevinOConnor

Copy link
Copy Markdown
Collaborator

define the M104/M109 also as macros

Yes. That's definitely possible. Off the top of my head - something like:

[gcode_macro M104]
rename_existing: M104.99
gcode:
    {% if params.get('T') in ['0', '1'] %}
        # Send T0 and T1 heater updates to T0
        M104.99 T0 S{params.S}
    {% else %}
        M104.99 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %}
    {% endif %}

-Kevin

@KevinOConnor

Copy link
Copy Markdown
Collaborator

Also - not sure if you were asking or not, but there is already a generic SET_HEATER_TEMPERATURE command (and a TEMPERATURE_WAIT command) - see docs/G-Codes.md.

-Kevin

@konsumverweigerer

Copy link
Copy Markdown
Contributor Author

Also - not sure if you were asking or not, but there is already a generic SET_HEATER_TEMPERATURE command (and a TEMPERATURE_WAIT command) - see docs/G-Codes.md.

The TEMPERATURE_WAITIs not the sane as the wait in the set_temperature: it checks if the heater is in a temp range but not if the heater is busy reaching its target...

@KevinOConnor

Copy link
Copy Markdown
Collaborator

The TEMPERATURE_WAITIs not the sane as the wait in the set_temperature: it checks if the heater is in a temp range but not if the heater is busy reaching its target...

That is true. It is possible to have a macro call the original M104 though (as shown at #3920 (comment) ).

-Kevin

@ETE-Design

Copy link
Copy Markdown

@konsumverweigerer @KevinOConnor Is anything missing, or is it ready for merge?

@KevinOConnor

Copy link
Copy Markdown
Collaborator

Any further updates on this?

-Kevin

@konsumverweigerer

konsumverweigerer commented May 3, 2021 via email

Copy link
Copy Markdown
Contributor Author

@matyay matyay left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hello,

I've been recently finishing my build of a 3D printer with a 3-to-1 mixing extruder. I've used code for this PR but I it didn't work at first. Then I've found some issues and after fixing them according to the comments I got the 3 filament drive motors to move correctly! I think you want to update your PR with the fixes. Anyways, great work!

move.cruise_t if hasattr(
move, "cruise_t") else move.min_move_t,
move.decel_t if hasattr(move, "decel_t") else 0.)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing return move

self.gradient_method = 'linear'
self.printer.register_event_handler("klippy:connect",
self.handle_connect)
logging.info("MixingExtruder %d extruders=%s", idx,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing second %s in the format string. Not critical but makes Python throw exceptions.

@ETE-Design

Copy link
Copy Markdown

@matyay Great, hope this PR will soon be finished and merged :-)

@KevinOConnor KevinOConnor added the other work first Topic waiting for other changes to complete label Jul 26, 2021
@binarylefmart

Copy link
Copy Markdown

this feature is it implement to the code ? wan't to build a mix color 3d printer on klipper :3

@ETE-Design

ETE-Design commented Aug 4, 2021

Copy link
Copy Markdown

@binarylefmart Not yet, seems like @KevinOConnor and the creator couldn't find a solition they both could accept :-( Seems to be stocked for now...

@matyay

matyay commented Aug 4, 2021

Copy link
Copy Markdown

Hi, This PR is originally from @konsumverweigerer so I actually can't update it. But I can issue a new one including his work plus mine.

I have this working on my machine. I even added automatic detection of retractions so that you don't need your slicer to emit firmware retractions (I actually did that because I couldn't find a way how to implement firmware retractions to work with mixing...).

Nevertheless since there is an interest in this feature I'll try to find some time and make a new PR, probably this weekend.

@kageurufu

Copy link
Copy Markdown
Contributor

@matyay I am interested, I have a 4 filament mixing extruder I have been wanting to mess with

@ETE-Design

Copy link
Copy Markdown

@matyay mabye you should make a new PR, so if you make a good solution, @KevinOConnor could then merge it into the mainbranch :-)

@binarylefmart

Copy link
Copy Markdown

I'm very interested too ^^ if you could made a PR this Will be awesome !!

@matyay

matyay commented Aug 7, 2021

Copy link
Copy Markdown

Hi! As promised I've created another PR with my fixes and improvements to this one: #4566

@binarylefmart

Copy link
Copy Markdown

Hi @matyay, i tested the Branch but when i put the sample macro on my printer.cfg, this kill my mcu communication, i the nothing on klippy.log.
Have an idea ?

@ETE-Design

Copy link
Copy Markdown

@binarylefmart You tested this PR or #4566 , if Matyay's PR then pls. Write at his PR :-)

@binarylefmart

Copy link
Copy Markdown

Does the mixingextruder Branch Will be merge to the Master ? @KevinOConnor 😊😁🙏

@KevinOConnor KevinOConnor removed the other work first Topic waiting for other changes to complete label Jan 8, 2022
@KevinOConnor

Copy link
Copy Markdown
Collaborator

Thanks. I'm not sure what the state of this PR is. If there is still interest in this topic then the PR will need to be updated and a reviewer will need to volunteer to review it ( https://www.klipper3d.org/CONTRIBUTING.html ). Unfortunately, due to time constraints on my side it is unlikely I will be reviewing this PR.

A good place to discuss this PR, get testers, and engage a reviewer is on the Klipper Discourse server ( https://www.klipper3d.org/Contact.html ).

-Kevin

@KevinOConnor

Copy link
Copy Markdown
Collaborator

FYI, #5143 makes it possible to call SET_EXTRUDER_STEP_DISTANCE on extruder_stepper objects, which may make it possible to implement mixing extruders via extruder_stepper objects.

-Kevin

@github-actions

Copy link
Copy Markdown

Unfortunately a reviewer has not assigned themselves to this GitHub Pull Request and it is therefore being closed. It is a good idea to move further discussion to the Klipper Discourse server. Reviewers can reach out on that forum to let you know if they are interested and when they are available.

Best regards,
~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

@github-actions github-actions Bot closed this Mar 14, 2022
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants