Closed lylecheatham closed 6 years ago
That's a great analysis that you have done there. I have already had a discussion with some of the Cura devs about the fact that it generates a lot of small extrusions (I noticed them because they actually triggered a bug in my printer firmware). Because I build Cura from source, I have added a little bit of code to replace extrusions less than 5um long with moves. Perhaps, given what you say above, I should just ignore those short extrusions completely.
See #591.
My current fix to this problem is probably going to be a python post-processor script that just deletes the micron moves, but that is just a big band-aid. I'm not too familiar with the code base but applying something similar in Cura, or even finding the root cause of these micron moves would probably be best.
The interesting thing about this problem, is that I would probably expect this to be a 'bug' in pretty much any GRBL based Firmware, which probably makes up 80%+ of the community. The only things necessary to bring it out are either a high st/mm extruder (fairly common, especially on 2.85mm systems) or high st/mm XY axes (less common, but still should not be alienated). Also untested, but I'm fairly certain a high extrusion multiplier could also trigger this.
I saw some discussion on #591 on whether the slicer or the firmware should be filtering them, and in my opinion it is a two sided fix. The slicer should not generate unreasonable moves, and the printer should not execute moves it deems unreasonable (e.g. moves that are smaller than a reasonable mechanical tolerance for the machine). However, depending on the quality and precision of your machine, or depending on the extrusion multiplier, this could be considered a reasonable move.
I disagree with the printer ignoring moves it deems unreasonable because the gcode may have been written or programmed for precisely the effect you descibe. I don't know why someone would want to do that, but that is precisely the point. You can never know what weird stuff someone might want to do with the printer. The move itself may be nonsensical, but the deceleration may be what the writer of the code wants. Or indeed a slicer. If it is indeed a bad move, a slicer should not generate it.
Wow, I'm seriously impressed with the amount of work & logging you put into this. I don't say this lightly; I wish more bug reports were this detailed!
The argument for the printer removing them (at least how I understood it) was because of the printer not being able to keep up with the speed of processing required for making moves of <5 micrometres. You need a lot of processing power to draw a curve of 20,000 line segments in 0.5s. That's not something a slicer should have to take into account.
This argument is different and valid. If Cura is making erroneous moves that cause the acceleration and jerk to kick in at the firmware, that is expected result in the firmware and unexpected result from Cura.
I've made this regex to find such micron moves:
G1 [F\d\. ]*(X\d+\.\d{2})\d* (Y\d+\.\d{2})\d* [Z\d\. ]*[E\d\.]*\nG1 [F\d\. ]*\1\d* \2\d* [Z\d\. ]*[E\d\. ]*
Hey all,
Glad everyone is enjoying the depth of the bug report. The main reason it got that deep is because I originally thought it was a firmware bug, and spent a while tracking it down on Smoothieware, eventually I came to the realization that it was all due to strange input from Cura, I already had all the hardware logging set up so I figured I might as well include it. I also wanted to check if it existed in Marlin because if I could replicated it in two implementations of GRBL, I could extrapolate that it's probably a problem in almost every firmware variant that implements GRBL
About the printer filter vs slicer filter, I think it's a pretty philosophical discussion, but I wrote my take below. Note that this is just my friendly addition to the conversation, no offense taken if you disagree
I think G1/G0s should be used to define waypoints for the printer, with very little guidance on how they get from one to the next. You might point out that there is a feedrate attached to G1/G0, but on the firmware side of things, it is taken merely as a suggestion. Once the printer receives these G-Codes, it is entirely up to the firmware on how to get from one waypoint to another.
One thing the firmware needs to consider with these waypoints is tolerance. At any given moment, the nozzle has a slop of tens, sometimes hundreds of microns. So as the print is running along, and it is coming from point A to point B 100mm away, and then immediately after is point C 1 micron away from point B, it has essentially hit point C and B at the same time due to real world tolerances. For planning purposes, there is no reason to plan a line between these two almost-identical points, so we should filter one of them out.
Now, to address @DDDirk's concerns of 'what if the G-code was there to get this exact effect?' and this is where I go back to these waypoints having little guidance on how. If the slicer desires behavior like this, I think it should not attain it through the use of G1/G0, it should use other G-Codes more closely tied with the 'how' of printing. An example of one of those codes would be G4 dwell. this exact effect could be achieved with a G4 S0, which introduces a stop in the planner.
On the slicer side, I think these should be filtered purely because it's unintentional and takes up space/bandwidth at no benefit (and occasionally some detriment) to the part.
Of course another argument, as @Ghostkeeper brought up, is bandwidth. Many firmwares lock up if you give it G-codes too fine, especially Marlin which physically can not send the G-Code fast enough due to the 250 Kbaud hardware serial connection. Unrelated to this, but I find the continued use of hardware serial in 3D printers to be almost comical, for the price of an FTDI chip you could just upgrade to a microcontroller with USB built in, and then you have a much faster connection (USB standard is 12Mb/s).
Ever since I found the issue with the printer firmware getting upset by very small extrusions I have been using the following..
void LayerPlan::addExtrusionMove(Point p, const GCodePathConfig& config, SpaceFillType space_fill_type, float flow, bool spiralize, double speed_factor)
{
// ignore extrusions less than 5uM long
if(vSize2(p - *last_planned_position) >= 25)
{
getLatestPathWithConfig(config, space_fill_type, flow, spiralize, speed_factor)->points.push_back(p);
last_planned_position = p;
}
}
That only emits extrusions that are at least 5um long. Needless to say, I can't see any visual difference in the print quality. Unless you can fix all the places where the short extrusions are being generated, I think you have to filter them out like this to avoid the kind of problems that the OP has so expertly identified.
All right, after investigating a bit, I've made a fix similar to Smartavionics', but more specific. The problem, I think, was that the rafts are offset with a large offset and a round joint type. This round joint type introduced a lot of extra vertices with small details, which in itself isn't a problem but it apparently is if you then do an inset because the vertices at the start and end of the rounded corner fell 1 micron next to the longer line. We do the inset with half a line width because the nozzle needs to move through the centre of the line but we want the outside edge of the line to coincide with the original polygon, not the centre.
I'm calling the simplify()
function on the polygon in question. This does something similar to Smartavionics' idea.
So that one's fixed in fb5a705c6ff3dd7793732be2454b246d3addac5a. I'm not getting these movements any more now. At least not with the raft, and I couldn't find them elsewhere.
That's great but I see loads of extrusions less than 5um long and I never use rafts!
Related to this discussion. See #614 for a fix for short segments being created in zigzags which were triggering unnecessary travel moves even when the short extrusion was thrown away.
I fixed the micron moves in the rafts for 3.0 and the micron moves in zigzag patterns were fixed by Smartavionics for 3.1. We believe they don't occur any more now.
However, there is still an outstanding PR for a fix to zigzags (see #629). This needs to be merged.
I've taken to calling this anomaly a "Micron Move"
In the Gcode generated for curves, there is occasionally a very small move in a seemingly random direction. So far I have only observed this in Rafts, but frankly it could be happening everywhere, I just haven't stared at the printer for long enough.
Below is a excerpt from real Gcode, generated in Cura 2.7, stock settings (except for raft turned on)
Excerpt 1. Micron moves in a harmless direction
Here is an example of a random micron move in a harmless direction. In this example we are moving in the X-, Y+ direction. On line 60 we get a micron move in the positive Y direction, which has no effect on the print.
This manifestation of the bug causes no problems in the print, as the planner will just glide right over it.
Excerpt 2. Micron moves in a harmful direction
This is an example of a random micron move in a harmful direction. In this example we are moving in the X-, Y- direction, however on line 134 we get a micron move in the positive X direction. This is highly problematic because the GRBL planner (used in almost every firmware) sees this and interprets it as a line segment in the opposite direction. To complete this, it must come to a full stop from the curve it was making, move backwards by one step, and then accelerate back up to speed. Side Note: This excerpt also contains a harmless micron move on line 132
Here are some images that demonstrate this behavior on stock Marlin 1.1.5. I ran it on a RUMBA board hooked up to a Saleae Logic analyzer, and then ran the capture through a python script to extract the movement data. These are shown in Figures 1-4. When reading these graphs you can ignore the position and acceleration data in these captures, the interesting bits are in the Velocity traces.
In Figure 1, we see that the printer is making what essentially amounts to a square with rounded corners, and during the corners, it occasionally slows to a dead stop and then speeds back up. Doing a movement like this will cause printers to pool plastic along the bead, and also increases print times.
Figure 1. Micron Moves at 29.5s, 35.3s, 35.5s, 35.7s and 35.9s
Zooming further on the anomaly in Figure 1, we see that what is really happening is that the X, Y, and E axes come to a full stop, and then the X axis makes a very small movement in the opposite direction. This can be seen in Figures 2 and 3.
Figure 2. Zooming in on the move at 29.5s Figure 3. Further zoom on the move at 29.5s
For a clearer view of this, we can look at the raw Logic captures. In Figures 4 and 5, we can see that it slows to a halt, then the X axis reverses direction for a short while, and then we pick back up to speed in the direction we were going initially.
Figure 4. Logic Capture of the move at 29.5s
Figure 5. Zoomed Logic Capture of the move at 29.5s
To show that this problem is exactly what I'm saying it is, If I remove line 64 from Excerpt 2, as demonstrated in Excerpt 3 and run it, the first spike will disappear. Please note, the times will not align from the second capture because I am just triggering it by hand.
Excerpt 3. Micron move from Excerpt 2 removed
Figure 6. shows the same print, with the micron move on line 134 removed.
Figure 6. Micron move removed
Clearly line 134 had a large impact on the print. That small micron move caused the printer to come to a complete stop, which would impact print quality on curves. Micron moves seem to be prevalent throughout Gcodes generated by Cura, but most of the time have no impact on the print because they are in the same direction that the printhead was moving originally.
-Lyle Cheatham
Attached is the Gcode file I was running. Please note that I deleted several lines related to temperature as I am just running a detached RUMBA board hooked up to my logic analyzer on my desk, and I didn't want temp commands causing strange behavior.
Also attached is the config file I used for Marlin 1.1.5 if you are looking to replicate. I set steps/mm all the way up to 1000 to ensure that the problem would show through. If the Micron move does not generate any steps GRBL will throw the move away.
attach.zip