-
-
Notifications
You must be signed in to change notification settings - Fork 19.2k
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
Implements clean nozzle feature (Lulzbot's REWIPE) #4054
Implements clean nozzle feature (Lulzbot's REWIPE) #4054
Conversation
be7732e
to
7005de4
Compare
|
||
#include "point_t.h" | ||
|
||
extern void do_blocking_move_to(float x, float y, float z); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thinkyhead give me a hand here, when outside Marlin_main.cpp
scope what is the best way to accomplish movement ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we're getting ahead of ourselves making every new thing into a class (especially non-static classes that pass a this
to every method call). Could we make an effort from now on to make all the data and methods static
in classes where we will only ever have a single instance? Otherwise, I will need to scrub all the classes and do it myself, which is tedious.
The other thing about putting every new thing into a class in its own compilation unit is, as you see, sacrificing the optimizations gained by implementing such things within Marlin_main
alone. And I wonder if this effort at organization, placing everything into little classes, isn't going to come up and bite us in the ass in the long run. We are already bloating the code way beyond my initial hope of keeping it fitting on smaller boards for this release.
Anyway, if you want to access a function in Marlin_main.cpp
, you will need to move its declaration to Marlin.h
. If the compiler was inlining it, then it won't do that anymore, so we will lose any compiler optimization that was gained by having it declared in a single unit. Maybe some of these movement functions —the convenience functions which only wrap others— can be defined in Marlin.h
as inline
…. At least ensure they aren't expanded into a call from a call from a call…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first iteration I did was static but not knowing the future reverted back to non-static as the binary size was the same (we may have four nozzles, etc) but Ido agree with your principle for static and we should make clear that will be the norm.
I believe there is only one road to OOP, we must break with the past. I may be over killing with dynamic classes but the reason for that is that we dont know know the future or what we will require. The problem is every new class is bloated because old code does not re-use them.
GCC also inlines methods, there is no reason movement
to be restrained in Marlin_main.cpp
. IMO we must change the mindset that everything must be optimized, we must optimize code that runs most of the time for speed and the other part for size (80-20 rule).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we should avoid optimizing for speed where it matters little. But we should optimize for size at every opportunity. In some cases optimizing for size means replacing inline code with function calls, sacrificing a little performance, and I agree that is fine where code performance hardly matters, such as in the LCD and leveling routines. Easier-to-read code in homing and leveling will be better, even if it's slower.
I also agree, movement should be available all over the place, wherever we might need to utilize it in other classes. We can probably break out a lot of the general-purpose functions into separate compilation units from Marlin_main
. In fact, I'm sure we will end up splitting it into a few different files based on types of functions - temperature, movement, etc.
@jbrazio I'm not sure if you have a wiper-pad setup, if you don't I can always help test and debug. |
// /| /| /| (Xe, Ye) | ||
// / | / | / | | ||
// / | / | / | | ||
// (Xs, Ys) / |/ |/ | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Great idea to do a zig-zag pattern!
850335f
to
295e1b4
Compare
@scalez that would be great as I don't have the cleaning pad setup. BTW, what type of material do you use for the cleaning pad, can we DIY something like that ? |
bd52a43
to
ce1f498
Compare
@jbrazio we have the instructions on how to make it here: https://devel.lulzbot.com/wiper_pads/wiper_pad_manufacture_SOP.odt |
@scalez it passes the Travis test now, did you had the opportunity to test ? |
@jbrazio I'll try to test it today, if not Monday. |
@jbrazio: I just tried it out a bit. It works really well. Here are my initial thoughts:
static void zigzag(point_t const &start, point_t const &end, uint8_t const &triangles)
__attribute__ ((optimize ("Os"))) {
// Calculate the triangle side
float const a = fabs(end.x - start.x) / triangles;
// Don't allow the sides (a, b) to be smaller than 5mm
if (a < 5 || fabs(end.y - start.y) < 5) return;
// Move to the starting point
do_blocking_move_to_xy(start.x, start.y);
do_blocking_move_to_z(start.z);
// Start the zig-zag pattern
for (uint8_t i = 0; i < triangles; i++) {
float const x = start.x + (a * (i + 1));
do_blocking_move_to_xy(x, end.y);
do_blocking_move_to_y(start.y);
}
}
for (uint8_t i = 0; i < triangles; i++) {
float const Y = start.Y + (B * (i + 1));
do_blocking_move_to_xy(end.x, y);
do_blocking_move_to_X(start.X);
}
|
I like this feature. we do it like this: I would like to see this after a filament change as well |
This could lead to collisions in some cases. You need to be sure that the X (or XY) gantry cannot crash into the part on the build plate. Usually this means you can't lower the X (or XY) gantry back down to the bed (at many points) once the object reaches a certain height. If your wipe-surface moves with the gantry, this is not a problem. If the wipe surface is at the back of the bed, perhaps most of the time the object can be avoided. I suppose the machine could keep track of the farthest points where extrusion has occurred to "guess" the size of the object on the plate, and make sure to avoid that region. |
Make "nozzle wipe after retraction" true or false and let the manufacturer of the machine make the decision. I would not try to do elaborate things in firmware. |
I tend to agree. Nozzle wipe should be slicer-initiated as part of the full control program, when switching nozzles or whatever. Software that generates the GCode should decide where to move based on configured clearance values, and whether a wipe is possible given the position of the wipe surface. I'm not sure whether this is an option in current slicers. |
OK we have a new pattern generator for // P1: This starts a zig-zag pattern between (X0, Y0) and (X1, Y1), "T"
// defines the number of zig-zag triangles to be done. "S" defines the
// number of strokes aka one back-and-forth movement. As an example
// sending "G12 P1 S1 T3" will execute:
//
// --
// | (X0, Y1) | /\ /\ /\ | (X1, Y1)
// | | / \ / \ / \ |
// A | | / \ / \ / \ |
// | | / \ / \ / \ |
// | (X0, Y0) | / \/ \/ \ | (X1, Y0)
// -- +--------------------------------+
// |________|_________|_________|
// T1 T2 T3 Please note that now the zig-zag will return to the "initial" position from where |
5ed899b
to
35d8292
Compare
35d8292
to
4937f9a
Compare
@thinkyhead travis is running, if green then this PR is ready to be merged. |
Yes, it certainly is! |
When
|
Historically this is correct, because this nozzle-probes, where the feature is made for, are only used for probing - never for homing. This systems have a separate z-endstop for homing.
|
This PR needs "rebasing" to take advantage of the @esenapaj @Blue-Marlin do you agree we can have the nozzle clean feature without a probe right ? For instance I have replaced my start-gcode clean/purge procedure with a call to |
*to_xy is still lingering somewhere around. |
I think that it's better that this feature is freed from restrict of ...But, possibly sludge of filament on outside of nozzle can be removed if strong organic solvent is used with cleaning pad. |
Possibly
It's actually fine for functions only used in a single compilation unit (
Menu > Clean Nozzle > Cold Pull ?
|
It's interesting, but in case of using a "filament for cleaning" like a Dyna-Purge, it needs more length of extrude. And, I think the feature can be used for pri-process of printing and change-process of multi-nozzle like this...? |
But, I feel that these recherche features might be as well considered after 1.1.0... |
@esenapaj so your wipe is done during toolhead changes. Do you depend on wiping for your probing scheme? Or would you do a purge and cold pull before each probe? |
Sorry, above video isn't mine. I introduced above video for technological study. |
@scalez that video was just an example @esenapaj was giving us. |
This is the implementation for the @alephobjects
REWIPE
feature discussed at #3553 by @scalez.Do not merge yet this PR as it still requires some tweaks, including the update of all example config files.